Xpath с html5lib в PHP
У меня есть этот основной код, который не работает. Как я могу использовать Xpath с html5lib php? Или Xpath с HTML5 любым другим способом.
$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')
работает.
2 ответа
Похоже, что 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"
}
Использование 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
disable_html_ns
(логическое значение): предотвращает автоматическое назначение синтаксическим анализатором пространства имен HTML5 документу DOM. Это для инструментов DOM, не поддерживающих пространство имен.