XPath谓词中的双斜杠与路径本身相同

时间:2012-04-07 11:06:40

标签: xpath

我使用XPather进行了不同的XPath查询(仅适用于较旧的firefox版本)并注意到以下查询的结果之间存在差异

这个显示了一些结果

//div[descendant::table/descendant::td[4]] 

这个列出空列表

//div[//table//td[4]]

由于某些规则它们是否不同,或者只是XPath解释器的特定实现的不当行为? (看起来像是从FF引擎中使用,XPather只是一个非常简单的用于查询的GUI)

2 个答案:

答案 0 :(得分:8)

使用XPath 1.0 ///descendant-or-self::node()/的缩写,因此第一条路径为/descendant-or-self::node()/div[descendant::table/descendant::td[4]],而第二条路径与/descendant-or-self::node()/div[/descendant-or-self::node()/table/descendant-or-self::node()/td[4]]完全不同。因此,主要区别在于,在第一个谓词中,您会查看相对于div元素的后代,而在第二个谓词中,您会查看来自根节点/(也称为文档节点)的后代。 您可能希望//div[.//table//td[4]]使第二个路径表达式更接近第一个路径表达式。

[编辑] 这是一个示例:

<html>
  <body>
    <div>
      <table>
        <tbody>
          <tr>
            <td>1</td>
          </tr>
          <tr>
            <td>2</td>
          </tr>
          <tr>
            <td>3</td>
          </tr>
          <tr>
            <td>4</td>
          </tr>
        </tbody>
      </table>
    </div>
  </body>
</html>

使用该示例,路径//div[descendant::table/descendant::td[4]]会选择div元素,因为它有一个table子项,其中有第四个td后代。

然而,对于//div[.//table//td[4]],我们会查找//div[./descendant-or-self::node()/table/descendant-or-self::node()/td[4]],它是//div[./descendant-or-self::node()/table/descendant-or-self::node()/child::td[4]]的缩写,并且没有元素具有第四个td子元素。

我希望这能解释不同之处,如果您使用//div[.//table/descendant::td[4]],那么您应该得到与原始表单相同的结果。

答案 1 :(得分:4)

关于XPath的W3C文档中有一个重要的注释:

  

XML Path Language (XPath) Version 1.0
  2 Location Paths
  2.5 Abbreviated Syntax

     

注意:位置路径//para[1]与位置路径/descendant::para[1]的含义不同。后者选择第一个后代para元素;前者选择所有后代para元素,这些元素是他们父母的第一个孩子。

这意味着路径中的双斜杠不仅是/descendant-or-self::node()/的快捷方式,而且是XML树迭代的下一级的起点,这意味着//右侧的步骤表达式在当前上下文节点的每个后代上重新运行。

所以这条路径中谓词的确切含义

//div[ descendant::table/descendant::td[4] ]

是:

  • 构建一系列所有<table>个节点后代到当前<div>
  • 对于每个此类<table>构建,所有后代<td>元素的序列将它们连接成一个序列,
  • 过滤该第四项的序列。

最后,路径返回文档中的所有<div>元素,这些元素在其所有嵌套表中至少有四个数据单元格。由于文档中有4个单元格或更多单元格(当然包括嵌套表格中的单元格),因此整个表达式选择各自的<div>祖先。

另一方面,

中的谓词
//div[ //table//td[4] ]

表示:

  • 扫描整个文档树中的<table>元素(更准确地说,测试根节点和每个根的后代,如果它有<table>子元素),
  • 对于找到的每个表,扫描其子树以查找具有第四个<td>子元素的元素(即测试该表或其任何后代是否至少有四个<td>个子元素。)

请注意,谓词子表达式不依赖于上下文节点。它是一个全局路径,解析为某些节点序列(可能为空),因此谓词布尔值仅取决于文档的结构。如果为真,则整个路径返回文档中所有<div>元素的序列,否则返回空序列。

如果任何表中有一个元素,有4个(至少)数据单元格,那么谓词将 true
并且据我所知,所有<tr>行包含两个或三个单元格 - 没有包含4个或更多<td>子元素的元素,因此谓词子表达式返回空序列,谓词为 false 并且整个路径被过滤掉。结果是:没有(空序列)。