【发布时间】:2011-02-01 06:15:08
【问题描述】:
什么是 XPath(在 C# API 到 XDocument.XPathSelectElements(xpath, nsman) 如果重要的话)从这个文档中查询所有 MyNodes?
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<MyNode xmlns="lcmp" attr="true">
<subnode />
</MyNode>
</configuration>
- 我尝试了
/configuration/MyNode,这是错误的,因为它忽略了命名空间。 - 我试过
/configuration/lcmp:MyNode是错误的,因为lcmp是URI,而不是前缀。 - 我尝试了
/configuration/{lcmp}MyNode,但失败了,因为Additional information: '/configuration/{lcmp}MyNode' has an invalid token.
编辑:我不能像一些回答者建议的那样使用mgr.AddNamespace("df", "lcmp");。这要求 XML 解析程序提前知道我计划使用的所有名称空间。由于这适用于任何源文件,因此我不知道要为哪些命名空间手动添加前缀。 {my uri} 似乎是 XPath 语法,但微软没有费心去实现它……真的吗?
【问题讨论】:
-
目前尚不清楚您想要实现的确切目标。确定您正在寻找哪些节点的标准是什么?您是否正在根据名称空间寻找元素?在这种情况下,您的代码将知道命名空间。至于 {my uri} 是“XPath 语法”,您认为在 XPath 1.0 规范中的什么地方定义了该语法?无论您是把命名空间 URI 放在大括号中还是将命名空间 URI 传递给 AddNamespace 方法,这对您的 C# 代码都无关紧要,在这两种情况下,命名空间 URI 都需要作为字符串提供。
-
@Martin:我确实想在 XPath 中指定命名空间,但我只有命名空间 URI,没有命名空间前缀。我仔细研究了我“发明” {} 的地方,我可能略读不正确......我从这个参考中得到它:jclark.com/xml/xmlns.htm。感谢您指出了这一点。当然,即使它无效,它似乎也是一件有用的事情,能够轻松完成.. ;)
-
Scott,您需要选择任何您喜欢的允许前缀,使用 AddNamespace(prefix, namespaceURI) 将其与您拥有的名称空间 URI 相关联,并在您的 XPath 表达式中使用选择的前缀。这就是 XPath 的工作方式,至少是 XPath 1.0。前缀根本不必存在于输入 XML 中,也可以与输入 XML 中使用的不同,元素选择将基于命名空间匹配发生,而不是前缀。
-
如果您想使用 Clark 表示法,请考虑不使用 XPath,而是使用 LINQ to XML 轴方法,例如采用 XName 的 Descendants,它支持 {} 表示法。示例:
foreach (XElement myNode in doc.Descendants("{lcmp}MyNode"))。您当然也可以使用变量,例如XNamespace df = "lcmp"; foreach (XElement myNode in doc.Descendants(df + "MyNode"))
标签: c# xpath linq-to-xml xml-namespaces