4

我有这个不起作用的基本代码。如何将 Xpath 与 html5lib php 一起使用?或以任何其他方式使用 HTML5 的 Xpath。

$url = 'http://en.wikipedia.org/wiki/PHP';
$response = GuzzleHttp\get($url);

$html5 = new Masterminds\HTML5();
$dom = $html5->loadHTML($response);

$xpath = new DOMXPath($dom);

$elements = $xpath->query('//h1');
//$elements = $dom->getElementsByTagName('h1');

foreach ($elements as $element)
{
    var_dump($element);
}

未找到任何元素。使用$xpath->query('.')工程来获取根元素(通常 xpath 似乎有效)。$dom->getElementsByTagName('h1')正在工作中。

4

2 回答 2

5

使用disable_html_ns选项。

$url = 'http://en.wikipedia.org/wiki/PHP';
$response = GuzzleHttp\get($url)->getBody();
$html5 = new Masterminds\HTML5(array(
    'disable_html_ns' => true, // add `disable_html_ns` option
));
$dom = $html5->loadHTML($response);

$xpath = new DOMXPath($dom);
$elements = $xpath->query('//h1');

foreach ($elements as $element) {
    var_dump($element);
}

https://github.com/Masterminds/html5-php#options

disable_html_ns(boolean):防止解析器自动将 HTML5 命名空间分配给 DOM 文档。这适用于非命名空间感知 DOM 工具。

于 2015-05-16T17:05:51.553 回答
4

所以看起来 html5lib 正在为我们设置一个默认命名空间。

$url = 'http://en.wikipedia.org/wiki/PHP';
$response = GuzzleHttp\get($url)->getBody();
$html5 = new Masterminds\HTML5();
$dom = $html5->loadHTML($response);
$de = $dom->documentElement;
if ($de->isDefaultNamespace($de->namespaceURI)) {
    echo $de->namespaceURI . "\n";
}

这输出:

 http://www.w3.org/1999/xhtml

要使用 xpath 查询命名空间节点,您需要注册命名空间并在查询中使用前缀。

$xpath = new DOMXPath($dom);
$xpath->registerNamespace('n', $de->namespaceURI);

$elements = $xpath->query('//n:h1');
foreach ($elements as $element)
{
    echo $element->nodeValue;
}

这输出PHP.


通常,当涉及到默认命名空间时,我发现在 xpath 查询中为所有内容添加前缀很乏味,所以我只是去掉它。

$de = $dom->documentElement;
$de->removeAttributeNS($de->getAttributeNode("xmlns")->nodeValue,"");
$dom->loadXML($dom->saveXML()); // reload the existing dom, now sans default ns

之后,您可以使用原始 xpath,它会正常工作。

$elements = $xpath->query('//h1');
foreach ($elements as $element)
{
    echo $element->nodeValue;
}

这现在也输出PHP了。


因此,该示例的修改版本将类似于:

例子:

$url = 'http://en.wikipedia.org/wiki/PHP';
$response = GuzzleHttp\get($url)->getBody();
$html5 = new Masterminds\HTML5();
$dom = $html5->loadHTML($response);

$de = $dom->documentElement;
if ($de->isDefaultNamespace($de->namespaceURI)) {
    $de->removeAttributeNS($de->getAttributeNode("xmlns")->nodeValue,"");
    $dom->loadXML($dom->saveXML());
}

$xpath = new DOMXPath($dom);
$elements = $xpath->query('//h1');
foreach ($elements as $element)
{
    var_dump($element);
}

输出:

class DOMElement#11 (18) {
  public $tagName =>
  string(2) "h1"
  public $schemaTypeInfo =>
  NULL
  public $nodeName =>
  string(2) "h1"
  public $nodeValue =>
  string(3) "PHP"
  ...
  public $textContent =>
  string(3) "PHP"
}
于 2014-08-25T13:47:58.617 回答