我使用 XPather 处理了不同的 XPath 查询(仅适用于较旧的 firefox 版本),并注意到以下查询的结果之间存在差异
这显示了一些结果
//div[descendant::table/descendant::td[4]]
这个列出了空列表
//div[//table//td[4]]
它们是由于某些规则而不同,还是只是 XPath 解释器的特定实现的不当行为?(看起来像是从 FF 引擎中使用的,XPather 只是一个出色的简单 GUI 用于查询)
我使用 XPather 处理了不同的 XPath 查询(仅适用于较旧的 firefox 版本),并注意到以下查询的结果之间存在差异
这显示了一些结果
//div[descendant::table/descendant::td[4]]
这个列出了空列表
//div[//table//td[4]]
它们是由于某些规则而不同,还是只是 XPath 解释器的特定实现的不当行为?(看起来像是从 FF 引擎中使用的,XPather 只是一个出色的简单 GUI 用于查询)
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]]
which 的缩写,//div[./descendant-or-self::node()/table/descendant-or-self::node()/child::td[4]]
并且没有具有第四td
个子元素的元素。
我希望能解释差异,如果你使用,//div[.//table/descendant::td[4]]
那么你应该得到与原始表格相同的结果。
W3C 文档中有一条关于 XPath 1.0 的重要说明(W3C 建议 1999 年 11 月 16 日):
XML 路径语言 (XPath) 版本 1.0
2 位置路径
2.5 缩写语法注意:位置路径与位置路径
//para[1]
的含义不同/descendant::para[1]
。后者选择第一个后代para
元素;前者选择作为其父母para
的第一个孩子的所有后代元素。para
XPath 3.1 文档中的类似说明(W3C 建议 2017 年 3 月 21 日)
XML 路径语言 (XPath) 3.1
3 表达式
3.3 路径表达式
3.3.5 缩写语法注意:路径表达式与路径表达式
//para[1]
的含义不同/descendant::para[1]
。后者选择第一个后代para
元素;前者选择作为其各自父母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 个(至少)数据单元格,则谓词为真。
据我所知,所有行都包含两个或三个单元格 - 没有具有 4 个或更多子级的元素,因此谓词子表达式返回一个空序列,谓词为假,整个路径被过滤掉。结果是:没有(空序列)。<tr>
<td>