开发者

Select an XML node via XPath at an arbitrary depth

Having an XML document, I want to get the first node with a certain name, no matter in which nesting depth it is contained.

I tried several things without success:

var node1 = doc.SelectSingleNode(@"//Shortcut");
var node2 = doc.S开发者_开发技巧electSingleNode(@"/*/Shortcut");
var node3 = doc.SelectSingleNode(@"//*/Shortcut");
var node4 = doc.SelectSingleNode(@"*/Shortcut");
...

Each call results in a NULL node.

I think it should be some trivial XPath syntax. Can you help me?

(In case this matters: The XML document is an input file for a WiX project, so there could be some namespace issues involved?!?).

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);
...

Leading to the same results.

Edit 2 - Solution

I found the 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);

This succeeded.


The XPath expression that selects exactly the wanted node (and nothing in addition) is:

(//x:Shortcut)[1]

So, using:

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

where

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

in someNamespaceManager

This has an advantage over the proposed solution (to use SelectSingleNode()), because it can easily be adjusted to select the N-th wanted node in the XML document.

For example:

   (//x:Shortcut)[3]

selects the 3rd (in document order) x:Shortcut element, and

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

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


Why do not use XDocument?

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

IMO XDocument is faster and more readable than XPath.


I finally found the solution by 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);

This succeeded.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜