• Записи 162
  • Теги 66
  • Комментарии 330

Компьютерное

Особенности работы с HTML в PHP 8.4

В версиях PHP до 8.4 для очистки выборочной очистки HTML использовался класс DOMDocument, который изначально был предназначен для работы с XML. Однако в версии 8.4 его использование приводит к тому, что возвращается пустая строка. Стал искать решение, и выяснилось, что с этой версии именно для HTML появился новый класс: Dom\HTMLDocument, а для выборки с помощью XPath вместе с ним теперь следует использовать Dom\XPath.
В итоге код для обработки HTML приобретает примерно такой вид:
<?php
function process_html($html) {
    if (
version_compare(PHP_VERSION,'8.4','>=')) { // для PHP 8.4 и выше
      
$dom Dom\HTMLDocument::createFromString($html,LIBXML_HTML_NOIMPLIED);
      
$xpath = new Dom\XPath($dom);
    }
    else { 
// для более старых версий PHP
      
$html mb_encode_numericentity($html, [0x800x10FFFF0, ~0], $charset);      
      
$dom = new \DOMDocument('1.0',$charset);
      
$dom->formatOutput false;
      
$dom->loadHTML($htmlLIBXML_NONET|LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD); // LIBXML_NONET — for protection against XXE, LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD — to don't add DOCTYPE and html/body tags
      
$xpath = new DOMXPath($dom);            
    }

// TODO: код обработки

$result=$dom->saveHTML(); // возвращаем результат
if (version_compare(PHP_VERSION,'8.4','<')) $result = \mb_decode_numericentity($result,[0x800x10FFFF0, ~0], $charset);
return 
$result;
}


Ещё одно существенное отличие: Dom\XPath возвращает имена тегов в заглавном регистре, тогда как DOMXPath — в том регистре, в котором теги написаны в HTML-коде, что также может влиять на обработку.

1 комментарий:

4X_Pro
0

Ещё одна особенность выявилась: для Dom\XPath не работает поиск по имени тега, если импорт документа делать без опции Dom\HTML_NO_DEFAULT_NS.
Т.е. нужно примерно так: <?php
          $dom 
Dom\HTMLDocument::createFromString($html,Dom\HTML_NO_DEFAULT_NS);
          
$xpath = new Dom\XPath($dom);
          
$og_title $xpath->query('//meta[@property="og:title"]');

Написать комментарий


Задать вопрос