XPath

18 Мая 2020 17:32

Модуль XPath - более профессиональный подход к обработке html/xml документов. XPath быстр, способен работать с большими объемами данных и содержит в себе мощный синтаксис для поиска узлов. Однако, порог входа у XPath достаточно высок и необходимо чуть больше времени для понимания нежели чем у аналогов.

Чтобы начать с XPath нужно, для начала, убедиться в том, что он включен в системе. Используем phpinfo().

Установка настроек и попытка запарсить какой-нибудь ресурс

<?php
// Создаем поток
$opts = array(
  'http' => array(
    'method'  => 'GET',
    'timeout' => 10,
  ),
);

$context = stream_context_create($opts);

// Открываем файл с помощью HTTP-заголовков
$page_content = file_get_contents('http://spb.23met.ru/plist/mcspb?yclid=1779651014365578174#%D0%90%D1%80%D0%BC%D0%B0%D1%82%D1%83%D1%80%D0%B0%20%D0%903', false, $context);

/*
Либо с помощью cUrl
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, 'http://spb.23met.ru/plist/mcspb?yclid=1779651014365578174#%D0%90%D1%80%D0%BC%D0%B0%D1%82%D1%83%D1%80%D0%B0%20%D0%903');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
*/


libxml_use_internal_errors(true);

$page_dom = new \DOMDocument();

$page_dom->strictErrorChecking = false;
$page_dom->preserveWhiteSpace  = false;
$page_dom->validateOnParse     = true;

$page_dom->loadHTML('<?xml encoding="UTF-8">' . $page_content);
foreach ($page_dom->childNodes as $node) {
  if ($node->nodeType == XML_PI_NODE) {
    $page_dom->removeChild($node);
  }
}
$page_dom->encoding = 'UTF-8';

$page_xpath = new \DOMXPath($page_dom);

$tables = $page_xpath->query('//div[@id="right-container"]/table');
echo $tables->length;

Функции и свойства для работы

1. query(string $query);

Основная функция для выполнения запросов. В нее должен быть помещен шаблон выборки согласно синтаксису XPath.

$result = $xpath->query(string $query);

2. length;

Свойство, в котором хранится количество найденных узлов.

$result->length;

3. getAttribute($attributeName);

Получает значение атрибута выбранного узла.

foreach($result as $obj) {
    echo '<p>class: ' . $obj->getAttribute('class') . "</p>";
}

4. nodeValue;

Весь текст узла без тегов;

foreach($result as $obj) {
    echo '<p>' . $obj->nodeValue . "</p>";
}