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

本文关键字:选择 XML 节点 深度 任意 XPath 通过 | 更新日期: 2023-09-27 18:01:33

对于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在任意深度选择XML节点

精确选择所需节点的XPath表达式为:

(//x:Shortcut)[1]
使用:

,

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

,

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

in someNamespaceManager

这比建议的解决方案(使用SelectSingleNode())有一个优点,因为它可以很容易地调整为选择XML文档中的第n个所需节点。例如:

   (//x:Shortcut)[3]

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

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

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

为什么不使用XDocument?

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

我终于自己找到了解决办法:

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

这成功了。