Select XML node through XPath at arbitrary depth

Having an XML document, I want to get the first node with a specific name, regardless of the depth of its nesting.

I tried several things without success:

var node1 = doc.SelectSingleNode(@"//Shortcut"); var node2 = doc.SelectSingleNode(@"/*/Shortcut"); var node3 = doc.SelectSingleNode(@"//*/Shortcut"); var node4 = doc.SelectSingleNode(@"*/Shortcut"); ... 

Each call results in a NULL node.

I think this should be some kind of trivial XPath syntax. Can you help me?

(In this case: the XML document is the input file for the WiX project, so there may be some problems with the namespace?!?).

Edit

I also tried the following:

 var nsm = new XmlNamespaceManager(doc.NameTable); nsm.AddNamespace(string.Empty, @"http://schemas.microsoft.com/wix/2006/wi"); nsm.AddNamespace(@"ns", @"http://schemas.microsoft.com/wix/2006/wi"); 

together with:

 var node1 = doc.SelectSingleNode(@"//Shortcut", nsm); var node2 = doc.SelectSingleNode(@"/*/Shortcut", nsm); var node3 = doc.SelectSingleNode(@"//*/Shortcut", nsm); var node4 = doc.SelectSingleNode(@"*/Shortcut", nsm); ... 

Citing the same results.

Change 2 - Solution

I found a solution:

 var nsm = new XmlNamespaceManager(doc.NameTable); nsm.AddNamespace(string.Empty, @"http://schemas.microsoft.com/wix/2006/wi"); nsm.AddNamespace(@"ns", @"http://schemas.microsoft.com/wix/2006/wi"); 

and then

 var node1 = doc.SelectSingleNode(@"//ns:Shortcut", nsm); 

It succeeded.

+4
source share
3 answers

An XPath expression that selects the desired node (and nothing more) :

 (//x:Shortcut)[1] 

So using:

 doc.SelectNodes("(//x:Shortcut)[1]", someNamespaceManager) 

Where

the prefix "x" bound to the namespace "http://schemas.microsoft.com/wix/2006/wi"

in someNamespaceManager

This takes precedence over the proposed solution (use SelectSingleNode() ) because it can be easily customized to select the Nth desired node in the XML document .

For instance:

  (//x:Shortcut)[3] 

selects the third (in document order) x:Shortcut item and

  (//x:Shortcut)[last()] 

selects the last (in document order) x:Shortcut element in the XML document.

+2
source

Why not use an XDocument ?

 XDocument doc = XDocument.Load("test.xml"); doc.Descendants("Shortcut").First(); 

IMO XDocument is faster and more readable than XPath.

+2
source

I finally found a solution myself:

 var nsm = new XmlNamespaceManager(doc.NameTable); nsm.AddNamespace(string.Empty, @"http://schemas.microsoft.com/wix/2006/wi"); nsm.AddNamespace(@"ns", @"http://schemas.microsoft.com/wix/2006/wi"); 

and then

 var node1 = doc.SelectSingleNode(@"//ns:Shortcut", nsm); 

It succeeded.

+2
source

All Articles