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.
精彩评论