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

时间:2011-07-09 13:37:41

标签: c# xml xpath wix

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

这成功了。

3 个答案:

答案 0 :(得分:2)

为什么不使用XDocument

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

IMO XDocument比XPath更快,更易读。

答案 1 :(得分: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);

这成功了。

答案 2 :(得分:2)

精确选择所需节点的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()]

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