我有一个像这样的XML文件:
<lib:library>
<lib:book> XML </lib:book>
<lib:book> XPath </lib:book>
<lib:book> XSLT </lib:book>
<lib:book> Java </lib:book>
<lib:book> C++ </lib:book>
</lib:library>
我想去读书[2] ...我当然可以做像//lib:Book [2] ......这样的工作。可能会发生在我所拥有的相同XML文件中,例如,相同的标记名称但名称空间不同;在这种情况下,我的XPath表达式不起作用...
我可以替换它:
// * [local-name()=“book”]
这个表达式返回XML文件中包含的所有书...但是如果我想得到数字[2]怎么...我应该如何重写XPath表达式添加数字条件?当然我不想考虑命名空间,它必须对每个使用过的命名空间都有效。
由于 卢卡
答案 0 :(得分:4)
当前选择的答案错误。
实际上//someExpression[2]
可以选择多个节点。
例如,如果我们有以下XML文档:
<lib:library xmlns:lib="UNDEFINED!!!">
<topic name="XML">
<lib:book> XML </lib:book>
</topic>
<topic name="XPath">
<lib:book> XPath </lib:book>
</topic>
<topic name="XSLT">
<lib:book> XSLT1 </lib:book>
<lib:book> XSLT2 </lib:book>
</topic>
<topic name="Imperative PLs">
<lib:book> Java </lib:book>
<lib:book> C++ </lib:book>
</topic>
</lib:library>
表达式:
//*[local-name() = "book"][2]
根据上面的文档评估,选择了两个节点(并且它们都不是文档中具有所需属性的第二个节点):
<lib:book xmlns:lib="UNDEFINED!!!"> XSLT2 </lib:book>
<lib:book xmlns:lib="UNDEFINED!!!"> C++ </lib:book>
解决方案:在整个文档中选择N
(比如说第二个)节点(比如lib:book
)的一种方法是:
(//*[local-name() = "book"])[2]
在上面的文档中评估此表达式时,会选择正确的单个节点:
<lib:book xmlns:lib="UNDEFINED!!!"> XPath </lib:book>
解释:根据 W3C XPath recommendations 中的定义:
的缩写
//
是/descendant-or-self::node()/
因此:
//someName[2]
是:
的简写/descendant-or-self::node()/someName[2]
,这将选择名为someName
的文档中的任何元素,这是其父级的第二个someName
子级。
换句话说,[]
运算符比//
伪运算符绑定更强(具有更高的优先级)。这就是我们需要括号来覆盖默认运算符优先级的原因。
答案 1 :(得分:0)
//*[local-name() = "book"][2]
怎么样?它应该工作。
如评论中所述,除非您确定自己在做什么,否则应避免使用//
。