Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting an XElement with a namespace via XPathSelectElements

I have an XML e.g.

    <?xml version="1.0" encoding="utf-8"?>
    <A1>
       <B2>
          <C3 id="1">
             <D7>
                <E5 id="abc" />
             </D7>
             <D4 id="1">
                <E5 id="abc" />
             </D4>
             <D4 id="2">
                <E5 id="abc" />
             </D4>
          </C3>
       </B2>
    </A1>

This is may sample code:

    var xDoc = XDocument.Load("Test.xml");
    string xPath = "//B2/C3/D4";
    //or string xPath = "//B2/C3/D4[@id='1']";

    var eleList = xDoc.XPathSelectElements(xPath).ToList();
    foreach (var xElement in eleList)
    {
        Console.WriteLine(xElement);
    }

It works perfectly, but if I add a namespace to the root node A1, this code doesn't work. Upon searching for solutions, I found this one, but it uses the Descendants() method to query the XML. From my understanding, this solution would fail if I was searching for <E5> because the same tag exists for <D7>, <D4 id="1"> and <D4 id="2">

My requirement is to search if a node exists at a particular XPath. If there is a way of doing this using Descendants, I'd be delighted to use it. If not, please guide me on how to search using the name space.

My apologies in case this is a duplicate.

like image 723
Charlie Avatar asked Nov 08 '13 18:11

Charlie


2 Answers

To keep using XPath, you can use something link this:

var xDoc = XDocument.Parse(@"<?xml version='1.0' encoding='utf-8'?>
    <A1 xmlns='urn:sample'>
        <B2>
            <C3 id='1'>
                <D7><E5 id='abc' /></D7>
                <D4 id='1'><E5 id='abc' /></D4>
                <D4 id='2'><E5 id='abc' /></D4>
            </C3>
        </B2>
    </A1>");

// Notice this
XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("sample", "urn:sample");

string xPath = "//sample:B2/sample:C3/sample:D4";

var eleList = xDoc.XPathSelectElements(xPath, nsmgr).ToList();
foreach (var xElement in eleList)
{
    Console.WriteLine(xElement);
}
like image 147
Rubens Farias Avatar answered Sep 22 '22 02:09

Rubens Farias


but it uses the Descendants() method to query the XML. From my understanding, this solution would fail if I was searching for because the same tag exists for , and

I'm pretty sure you're not quite understanding how that works. From the MSDN documentation:

Returns a filtered collection of the descendant elements for this document or element, in document order. Only elements that have a matching XName are included in the collection.

So in your case, just do this:

xDoc.RootNode
    .Descendants("E5")
    .Where(n => n.Parent.Name.LocalName == "B4");
like image 30
Mike Perrenoud Avatar answered Sep 26 '22 02:09

Mike Perrenoud