php - 相同的 XPaths - 不同的结果

标签 php html xpath domdocument

$str = '
<body>
<table><tr><td><b class="1">1</b></td></tr></table>
<table><tr><td><b class="2">1</b></td></tr></table>
<p>some text</p>
</body>';

$dom = new DOMDocument();
$dom->loadHTML($str);
$xpath = new DOMXpath($dom);

foreach($xpath->query('//table[//b[contains(@class, "2")]]') as $i) 
   print_r($i);

echo "------------------------------------------\n";

foreach($xpath->query('//table//b[contains(@class, "2")]/ancestor::table') as $i) 
   print_r($i);

第一个 XPath 选择两个表,而第二个 XPath 仅获取目标(第二个)表。为什么?

test on eval.in

最佳答案

接受的答案纠正了错误,但并没有真正解释原始路径表达式出错的原因。

您的第一个表达式如下:

//table[//b[contains(@class, "2")]]

它有两个谓词,一个嵌套在另一个里面:

//table[//b[contains(@class, "2")]]
           ^---------------------^       inner predicate
       ^--------------------------^      outer predicate

将谓词视为应用于谓词左侧上下文的过滤器。在极端情况下,这种谓词要么不丢弃任何中间结果节点,要么丢弃所有中间结果节点。

只有当其右侧的谓词计算为 true 时,每个中间结果节点才会被保留.对于内部谓词:

//b[contains(@class, "2")]

//b产生一组中间体 b然后由谓词 b 过滤的元素节点(整个文档中的所有 [contains(@class, "2")] 元素节点) .给定您的输入 XML 文档,谓词中的表达式仅返回 true对于 b 中的一个元素。

但是//b[contains(@class, "2")]依次作为外部谓词的内容:

//table[outer predicate]

现在//table选择所有 table 作为中间结果整个文档中的元素节点,并为它们中的每一个检查谓词中的表达式。

重要的是,外部谓词 //b[contains(@class, "2")]将返回 true对于两者 table元素。这是因为对于他们两个来说,在整个文档的某处确实有一个 bclass 的元素属性包含 2 .

您实际上想做的是:从每个 table 的角度评估外部谓词表达式。元素 - 接受的答案显示了如何做到这一点。即,使用 .//而不是 //在谓词中。

关于php - 相同的 XPaths - 不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35314270/

相关文章:

php - 如何使用 php 和特定查询添加图像

php - Codeigniter 和 Google App Engine

php-fpm 访问日志应包含从 php 应用程序设置的自定义变量

android - 移动图像上传先处理?

javascript - 拖动和释放时的确认框在 IE11 中打开重复的确认框

XPath 仅获取嵌套 HTML 的第一个父级

xslt - 是否可以选择仅包含子节点子集的节点?

php - 如何在laravel网页中使用token认证

python-3.x - 即使直接从 Chrome 检查复制,XPath 也无法工作

javascript - 获取动态生成的下拉菜单Jquery的值