通过任意深度的XPath选择XML节点

有了XML文档,我希望得到第一个具有特定名称的节点,无论它包含哪个嵌套深度。

我尝试了几件事没有成功:

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

每次调用都会产生一个NULL节点。

我认为它应该是一些简单的XPath语法。 你能帮助我吗?

(如果这很重要:XML文档是WiX项目的输入文件,因此可能涉及一些命名空间问题?!?)。

编辑

我也尝试了以下内容:

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

和…一起:

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

导致相同的结果。

编辑2 – 解决方案

我找到了解决方案:

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

然后

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

这成功了。

精确选择所需节点的XPath表达式(另外没有)是

 (//x:Shortcut)[1] 

所以,使用:

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

哪里

前缀"x"绑定到命名空间"http://schemas.microsoft.com/wix/2006/wi"

someNamespaceManager

这比建议的解决方案(使用SelectSingleNode() )有优势,因为可以轻松调整它以选择XML文档中的第N个所需节点

例如:

  (//x:Shortcut)[3] 

选择第3个(按文档顺序) x:Shortcut元素,和

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

选择最后一个(按文档顺序) x:Shortcut XML文档中的x:Shortcut元素。

为什么不使用XDocument ?

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

IMO XDocument比XPath更快,更易读。

我终于找到了解决方案:

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

然后

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

这成功了。