XPath是(故意)不适用于您希望对只存在于XML文档中的某些未知名称空间使用相同的XPath表达式的情况。您需要提前知道名称空间,将名称空间声明为XPath处理器,并在表达式中使用该名称。 Martin和Dan的答案显示了如何在C#中完成此操作。
的原因难度最好在XML namespaces规格表示:
我们设想可扩展标记语言(XML),其中一个XML文档可能包含的元素和属性(这里被称为应用“标记词汇表“),它们是为多个软件模块定义和使用的。其中一个动机就是模块化:如果存在这样一个已被很好理解并且有可用软件的标记词汇,最好重新使用这个标记而不是重新发明它。
这种包含多个标记词汇表的文档带来了识别和碰撞的问题。软件模块需要能够识别它们设计处理的元素和属性,即使在面向其他软件包的标记使用相同元素名称或属性名称时出现“冲突”时也是如此。
这些考虑因素要求文档结构应该有名称构造,以避免来自不同标记词汇表的名称之间的冲突。本规范描述了一种机制,即XML名称空间,它通过将扩展名称分配给元素和属性来完成此操作。
也就是说,命名空间都应该被用来确保你知道你的文件正在谈论:是<head>
元素谈论序言XHTML文档或大人物领导一个AnatomyML文档中?你永远不会被认为对命名空间不可知,它几乎是你应该在任何XML词汇表中定义的第一件事情。
应该可以做你想做的事,但我不认为它可以在单个XPath表达式中完成。首先,您需要在文档中搜索并提取所有的namespaceURI,然后将它们添加到命名空间管理器中,然后运行您想要的实际XPath表达式(并且您需要知道有关文档中名称空间在此处的分布情况点,或者你有很多表达式运行)。我认为你可能最好使用XPath之外的东西(例如类似DOM或SAX的API)来查找名称空间URI,但是您也可以探索XPath名称空间轴(在XPath 1.0中),使用函数(在XPath 2.0 )或使用Oleg的"configuration/*[local-name() = 'MyNode']"
等表达式。无论如何,我认为你最好的选择是尽量避免编写名称空间不可知的XPath!为什么你提前不知道你的名字空间?你如何避免匹配你不想匹配的东西?
编辑 - 你知道namespaceURI吗?
所以事实证明,你的问题困扰了我们所有人。显然你知道命名空间URI,但是你不知道在XML文档中使用的命名空间前缀。的确,在这种情况下,没有使用名称空间前缀,并且URI成为定义它的默认namspace。关键要知道的是,选择的前缀(或缺少前缀)与您的XPath表达式(以及一般的XML解析)无关。当文档被表示为文本时,前缀/ xmlns属性只是将节点与名称空间URI相关联的一种方式。你可能想看看this answer,我试着澄清命名空间前缀。
您应该尝试用解析器认为的方式来思考XML文档 - 每个节点都有一个名称空间URI和一个本地名称。命名空间前缀/继承规则只是保存了很多次输入的URI。写下这种情况的一种方法是使用Clark记法:也就是说,你写了LocalNodeName,但这种记法通常只是用于文档 - XPath对这种记法一无所知。
相反,XPath使用自己的名称空间前缀。例如/ns1:root/ns2:node
。但是这些与原始XML文档中可能使用的任何前缀完全分离,并且与此无关。任何XPath实现都会有一种方法将它自己的前缀映射到名称空间URI。对于C#实现,您使用XmlNamespaceManager
,在Perl中提供了一个散列,xmllint使用命令行参数......因此,您只需为知道的名称空间URI创建一些任意前缀,然后在XPath表达式中使用此前缀。使用什么前缀并不重要,在XML中您只关心URI和localName的组合。
要记住的另一件事(通常是一个惊喜)是XPath不会执行名称空间继承。无论名称空间来自继承,xmlns属性还是命名空间前缀,都需要为每个具有名称空间的前缀添加前缀。此外,尽管您应该始终以URI和localNames的方式来思考,但也有从XML文档访问前缀的方法。很少有必要使用这些。
目前尚不清楚您想要达到的目标。确定您正在寻找哪个节点的标准是什么?你在寻找基于他们名字空间的元素吗?在这种情况下,你的代码会知道命名空间。 至于{my uri}是“XPath语法”,您认为XPath 1.0规范中的语法已被定义?无论您将名称空间URI放在大括号中还是将名称空间URI传递给AddNamespace方法都不会影响您的C#代码,在这两种情况下,名称空间URI都需要以字符串形式提供。 – 2010-03-27 11:36:38
@Martin:我想在XPath中指定名称空间,但我只有名称空间URI和没有名称空间前缀。我仔细观察了我发明'{}'的位置,并且我可能错误地剔除了...我从这个参考文献中获得了它:http://www.jclark.com/xml/xmlns.htm。感谢您指出了这一点。当然,即使它不是有效的,它似乎是一个有用的事情,可以轻松完成......;) – 2010-03-27 17:23:37
Scott,您需要选择任何允许的前缀,将其与您使用AddNamespace的名称空间URI相关联(前缀,namespaceURI),并在您的XPath表达式中使用选择的前缀。这就是XPath的工作方式,至少XPath 1.0。前缀不必在输入XML中存在,或者可以不同于输入XML中使用的前缀,元素选择将根据命名空间匹配发生,而不是前缀。 – 2010-03-27 17:45:59