【问题标题】:XPath expressionXPath 表达式
【发布时间】:2011-09-15 15:26:55
【问题描述】:

我有一个这样的 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 表达式不起作用...

我可以替换它:

//*[本地名称() = "书"]

这个表达式返回XML文件中包含的所有书籍...但是如果我想得到数字[2]...我应该如何重写XPath表达式添加关于数字的条件?当然我不想考虑命名空间,它必须对每个使用的命名空间都有效。

谢谢 卢卡

【问题讨论】:

  • 好问题,+1。这是一个常见问题解答。而且你知道目前你选错了答案吗?

标签: xml xpath


【解决方案1】:

当前选择的答案错误。

其实//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>

解决方案:在整个文档中选择Nth(比如第二个)节点(比如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 子级。

换句话说,[] 运算符的绑定比 // 伪运算符更强(具有更高的优先级)。这就是为什么我们需要括号来覆盖默认的运算符优先级。

【讨论】:

    【解决方案2】:

    //*[local-name() = "book"][2] 呢?它应该工作。

    如 cmets 中所述,您应避免使用 //,除非您真的确定自己在做什么。

    【讨论】:

    • 是的,它可以工作......那么这个表达式呢? //*[local-name() = 'book'][1]/[local-name() = 'author'][1] 假设 book 可以有多个作者作为孩子
    • @luca:我会说表达式返回第一本书的第一作者。
    • 这个答案是错误的。事实上//expression[2] 可以选择许多个节点。应谨慎使用 XPath // 伪运算符。
    猜你喜欢
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多