Por mais de 15 anos, a única forma de manipular HTML no PHP foi a classe DOMDocument, construída sobre o libxml2 — uma biblioteca que entende apenas HTML 4.01. Na prática, isso significa que marcações modernas, tags não fechadas e comportamentos de parsing que qualquer navegador trata normalmente acabavam gerando warnings, elementos deslocados ou simplesmente documentos quebrados. O PHP 8.4 introduziu a classe Dom\HTMLDocument, um parser HTML5 completo baseado no motor Lexbor, que segue o WHATWG HTML Living Standard — a mesma especificação que os navegadores implementam.
O problema com DOMDocument
Carregar HTML5 com a classe antiga sempre exigia suprimir warnings e ainda corria o risco de reordenar ou descartar elementos que o libxml2 não reconhecia:
$dom = new DOMDocument();
libxml_use_internal_errors(true); // precisa suprimir warnings manualmente
$dom->loadHTML('<article><p>Texto</p></article>');
// tags HTML5 como <article>, <section> e atributos modernos
// nem sempre são interpretados do jeito que o navegador interpretaria
Criando um documento com Dom\HTMLDocument
A nova classe não tem construtor público — os documentos são criados por métodos estáticos nomeados: createFromString(), createFromFile() e createEmpty(). Por padrão, ela já espera UTF-8 e não exige suprimir erros para HTML malformado, porque o parser resolve isso do mesmo jeito que um navegador resolveria:
use Dom\HTMLDocument;
$html = <<<'HTML'
<!doctype html>
<html>
<body>
<article class="post">
<h2>Título do post</h2>
<p>Primeiro parágrafo.</p>
</article>
</body>
</html>
HTML;
$dom = HTMLDocument::createFromString($html);
echo $dom->saveHtml();
Seletores CSS nativos: querySelector e querySelectorAll
Essa é a mudança mais sentida no dia a dia: não é mais preciso montar expressões XPath só para buscar um elemento. querySelector() devolve o primeiro elemento que casa com o seletor (ou null, se nenhum casar), e querySelectorAll() devolve todos os elementos que casam, na ordem do documento:
$dom = Dom\HTMLDocument::createFromString($html);
$titulo = $dom->querySelector('article.post > h2');
echo $titulo?->textContent; // Título do post
foreach ($dom->querySelectorAll('article p') as $paragrafo) {
echo $paragrafo->textContent . PHP_EOL;
}
Chamar querySelector() a partir de um elemento (em vez do documento) limita a busca aos descendentes daquele elemento, o que é útil para escopar a busca dentro de um bloco específico já encontrado antes.
Lendo HTML de uma página real
Um uso comum é extrair dados de uma página baixada de outro lugar, algo que antes exigia muita cautela com o parser antigo:
$dom = Dom\HTMLDocument::createFromString($htmlDaPagina);
$links = [];
foreach ($dom->querySelectorAll('nav a') as $link) {
$links[] = [
'texto' => trim($link->textContent),
'href' => $link->getAttribute('href'),
];
}
Quando usar
- Web scraping e extração de dados de páginas HTML reais, incluindo marcação HTML5 moderna que o parser antigo interpretava errado.
- Templates e geração de HTML server-side em que você precisa inspecionar ou modificar um fragmento antes de enviá-lo.
- Testes automatizados que verificam a estrutura do HTML renderizado por uma aplicação, usando seletores CSS em vez de XPath.
- Qualquer código que hoje suprime erros de
DOMDocument::loadHTML()só para lidar com HTML que o libxml2 não entende corretamente.
Cuidados
Dom\HTMLDocument é uma classe nova, separada de DOMDocument — não é uma troca de comportamento na classe antiga, então código existente continua funcionando exatamente como antes. As duas classes não são intercambiáveis: um objeto Dom\HTMLDocument não pode ser passado para uma função que espera um DOMDocument clássico. Além disso, assim como no navegador, HTML malformado é corrigido silenciosamente (tags implícitas de <html>, <head> e <body> podem ser inseridas automaticamente), o que é exatamente o comportamento esperado, mas pode surpreender quem espera um retorno fiel byte a byte do que foi passado.
Compatibilidade
Dom\HTMLDocument foi introduzida no PHP 8.4 (lançado em novembro de 2024) e exige essa versão ou superior — não há como usá-la em versões anteriores, já que depende do novo motor de parsing Lexbor incluído na extensão DOM a partir dessa release.
Conclusão
Dom\HTMLDocument traz o PHP para o mesmo padrão de interpretação de HTML que os navegadores já usam há anos, eliminando as gambiarras que cercavam o DOMDocument clássico ao lidar com marcação moderna. Combinada com querySelector() e querySelectorAll(), ela torna scraping, parsing de templates e manipulação de HTML no servidor muito mais parecidos com o que já é familiar do JavaScript no navegador.
0 Comentário
Deixe seu Comentário!
Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.