2

I'm sure I'm missing something simple here but I've wrestled with it for a few days. I'm hoping someone can point out what I am missing.

I receive a XML message from an outside source in the following simplified format:

<root>
  <A>
    <B xmlns="http://www.something.com/Document>
      <C>Value1</C> 
      <D>Value2</D>
      <E>Value3</E>
    </B>
  </A>
  <A>
    <B xmlns="http://www.something.com/Document>
      <D>Value5</D>
      <E>Value6</E>
    </B>
  </A>
</root>

I'm trying to pull out the D elements.

I've tried:

XmlNodeList xmlResults = xdPayload.SelectNodes("//D")

This returned no results. Then thinking that the namespace was the issue I tried:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdPayload.NameTable);
xnlResults = xdPayload.SelectNodes("//D", nsmgr);

Again no results. I didn't think I needed to add in the default namespace but when thinking smart doesn't work think stupid. So I tried this:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdPayload.NameTable);
nsmgr.AddNamespace("", "http://www.something.com/Document");
xnlResults = xdPayload.SelectNodes("//D", nsmgr);

Still no results. I've tried more descriptive XPaths like "/root/A/B/D" and "/root/A/B[@xmlns="http://www.somewhere.com/Document"]/D" as well with no results as well.

I'm not sure what I'm missing here. Any help appreciated.

  • are you able to get the c node easily? how do you feel about getting the c node, then doing a .next() command? – Marker May 15 '18 at 18:36
  • I wouldn't mind going that route except 1) I cannot get C either and 2) C may or may not be there with every transmission. I probably should removed it from the second container for clarity. Sorry about that – C. Michael Warden May 15 '18 at 18:41
  • I don't know if this answer I once got would lead you down the correct path https://stackoverflow.com/questions/17068826/reading-an-xml-file-with-xdoc – Mike May 15 '18 at 18:44
  • or this https://stackoverflow.com/questions/4961805/xpath-and-selectnodes-method make sure your `AddNamespace is correct and not random ... what it would be ... idk – Mike May 15 '18 at 18:46

3 Answers3

3

Try adding a prefix-named namespace and then refer to the <D> as ns0:D:

NameTable nt = new NameTable();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
nsmgr.AddNamespace("ns0", "http://www.something.com/Document");
xnlResults = xdPayload.SelectNodes("/root/A/ns0:B/ns0:D", nsmgr);

This should select you the <D> elements for further processing.


If that doesn't work, you'll always have the option of ignoring all namespaces like with

XmlNodeList xmlResults = xdPayload.SelectNodes("//*[local-name()='D']")
zx485
  • 28,498
  • 28
  • 50
  • 59
  • The second option worked. I would have liked to been a bit more surgical about how I pulled these but for this particular application, it shouldn't cause any issues. Thanks for the assist!! – C. Michael Warden May 15 '18 at 20:57
2

Using XElement:

string text = @"
    <root>
        <A>
        <B xmlns='http://www.something.com/Document'>
            <C>Value1</C> 
            <D>Value2</D>
            <E>Value3</E>
        </B>
        </A>
        <A>
        <B xmlns='http://www.something.com/Document'>
            <D>Value5</D>
            <E>Value6</E>
        </B>
        </A>
    </root>";

XNamespace ns = "http://www.something.com/Document";
var xml = XElement.Parse(text);
var ds = xml.Descendants(ns + "D");
ds.ToList().ForEach(Console.WriteLine);
JohnyL
  • 6,894
  • 3
  • 22
  • 41
1

I struggled with the same issue. The key is the Descendants() method. Because you have <root> element, you have dig one level before you can start referring to the <A> and <B> elements.