Xpath 查询不匹配

Xpath query couldn't match

我有以下代码:

$content = 'whatever <iframe style="display:none;" src="https://www.example.com/hello/id"></iframe>';

$dom = new DOMDocument();
$dom->loadHTML($content);
$xp = new DOMXpath($dom);

$nodes = $xp->query("iframe[src*='.example.com/hello/']");

foreach($nodes as $node){
    echo $node->nodeName ." :  ". $node->nodeValue, PHP_EOL;
}

谁能告诉我为什么 Xpath 查询无法匹配 iframe?我做错了什么?

您的代码正在引发一些警告:

Warning: DOMXPath::query(): Invalid expression in ... on line ...

一个好主意是在您的服务器中显示这些警告,为此,请参阅 。


因此,您的 XPath 查询无效,这是因为您尝试搜索属性 src 以包含字符串的方式。

您正在使用的构造是 CSS 构造,而不是 XPath 构造。
XPath 中的等价物是

iframe[contains(@src, '.example.com/hello/')]

但是,您还没有完成,因为当您将 HTML 节点的随机部分提供给 DOMDocument 时,它会尝试使其成为有效的HTML 文件,然后做类似的事情:

<?php
$content = 'whatever <iframe style="display:none;" src="https://www.example.com/hello/id"></iframe>';

$dom = new DOMDocument();
$dom->loadHTML($content);
$dom->formatOutput = true;
echo $dom->saveXML();

会让您意识到您的 HTML 代码 — 来自 $content 的代码 — 变成了

<?xml version="1.0" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
  <body>
    <p>whatever <iframe style="display:none;" src="https://www.example.com/hello/id"/></p>
  </body>
</html>

从那以后,你有三个解决方案:

  • 要么在整个 HTML 文档中寻找任何匹配的 iframe
    //iframe[contains(@src,'.example.com/hello/')]
    
  • 要么你在它的特定级别点它html > body > p > iframe
    /html/body/p/iframe[contains(@src,'.example.com/hello/')]
    
  • 或者你在它的特定级别上用通配符指向它的父节点
    /*/*/*/iframe[contains(@src,'.example.com/hello/')]
    

一起

<?php
$content = 'whatever <iframe style="display:none;" src="https://www.example.com/hello/id"></iframe>';

$dom = new DOMDocument();
$dom->loadHTML($content);

$xp = new DOMXpath($dom);

echo $xp->query("//iframe[contains(@src,'.example.com/hello/')]")
        ->item(0)
        ->nodeName,
     PHP_EOL,
     $xp->query("/html/body/p/iframe[contains(@src,'.example.com/hello/')]")
        ->item(0)
        ->nodeName,
     PHP_EOL,
     $xp->query("/*/*/*/iframe[contains(@src,'.example.com/hello/')]")
        ->item(0)
        ->nodeName;

给出:

iframe
iframe
iframe