Guia de Referência da Biblioteca PHP libxml
Guia para a extensão PHP libxml: capture erros de análise, analise e valide XML com SimpleXML ou DOM, e evite XXE em entradas não confiáveis.
Este guia aborda a extensão PHP libxml: o que é, como os parsers XML do PHP reportam erros através dela e como analisar, validar e manipular XML com segurança. A ideia principal a reter é que libxml é a camada compartilhada de reporte de erros e configuração sob o SimpleXML, DOM e XMLReader — uma vez que você a entenda, toda extensão XML no PHP se torna mais fácil de depurar.
O que é o PHP libxml?
libxml é a biblioteca C que o PHP usa para quase todo o seu processamento XML. A extensão PHP libxml expõe o tratamento de erros e as opções do parser dessa biblioteca para o seu código. Você raramente a chama diretamente — em vez disso, usa uma extensão de nível mais alto que é construída sobre ela:
- SimpleXML — a forma rápida e semelhante a array para ler XML.
- DOM (
DOMDocument) — acesso completo de leitura/escrita à árvore do documento. XMLReader/XMLWriter— análise em streaming com uso eficiente de memória para arquivos grandes.
Quando qualquer uma dessas extensões encontra XML malformado, ela reporta o problema através do libxml. As funções libxml_* permitem capturar, inspecionar e limpar esses erros.
Instalando o PHP libxml
A extensão libxml está incluída e ativada por padrão — não há nada a instalar. Você pode confirmar que está ativa em tempo de execução:
<?php
var_dump(extension_loaded('libxml')); // bool(true)
echo LIBXML_DOTTED_VERSION; // e.g. "2.9.14" — the linked libxml2 version
?>Se uma compilação personalizada reportar false, recompile o PHP com --with-libxml (versões mais antigas do PHP usavam --enable-libxml).
Tratando erros do libxml
Esta é a parte mais importante da extensão. Por padrão, um documento malformado emite avisos do PHP, o que é difícil de tratar em produção. Em vez disso, alterne para o modo de erros internos: o libxml então coleta os erros em um buffer que você lê por conta própria.
<?php
// Stop warnings; buffer errors instead.
libxml_use_internal_errors(true);
$broken = '<root><item>unclosed</root>';
$xml = simplexml_load_string($broken);
if ($xml === false) {
foreach (libxml_get_errors() as $error) {
// Each $error is a LibXMLError object.
printf(
"[%s] line %d: %s",
$error->level === LIBXML_ERR_FATAL ? 'fatal' : 'warning',
$error->line,
trim($error->message)
);
echo PHP_EOL;
}
libxml_clear_errors(); // Empty the buffer so it doesn't leak into later parses.
}
?>Um LibXMLError expõe level (LIBXML_ERR_WARNING, LIBXML_ERR_ERROR, LIBXML_ERR_FATAL), code, message, line, column e file. Funções relacionadas:
libxml_use_internal_errors()— ativar/desativar o buffering.libxml_get_errors()— retornar todos os erros em buffer como um array.libxml_get_last_error()— retornar apenas o erro mais recente.libxml_clear_errors()— esvaziar o buffer.
Analisando Documentos XML
O uso mais comum de XML no PHP é a leitura de um documento. simplexml_load_string() (e seu equivalente para arquivos simplexml_load_file()) retornam false em caso de falha, portanto sempre os combine com o modo de erros internos:
<?php
libxml_use_internal_errors(true);
$source = '<catalog><book id="1">PHP Basics</book></catalog>';
$xml = simplexml_load_string($source);
if ($xml === false) {
echo "Failed to parse XML." . PHP_EOL;
foreach (libxml_get_errors() as $error) {
echo trim($error->message) . PHP_EOL;
}
libxml_clear_errors();
} else {
echo "Loaded: " . $xml->book . PHP_EOL; // Loaded: PHP Basics
echo "id = " . $xml->book['id'] . PHP_EOL; // id = 1
}
?>Opções do parser (constantes libxml)
A maioria das funções XML aceita um bitmask $options de constantes LIBXML_*. Combine-as com o operador OR bit a bit (|):
<?php
$xml = simplexml_load_string(
'<a> <b>text</b> </a>',
'SimpleXMLElement',
LIBXML_NOCDATA | LIBXML_NOBLANKS // drop CDATA wrappers + ignore whitespace-only nodes
);
echo $xml->b; // text
?>Opções frequentemente usadas:
| Constante | Efeito |
|---|---|
LIBXML_NOBLANKS | Remover nós em branco (somente espaço em branco). |
LIBXML_NOCDATA | Mesclar seções CDATA como texto simples. |
LIBXML_NOERROR / LIBXML_NOWARNING | Suprimir erros / avisos. |
LIBXML_COMPACT | Otimização de nós pequenos para documentos grandes. |
LIBXML_NOENT | Substituir entidades — perigoso com entradas não confiáveis (veja abaixo). |
Segurança: XML não confiável e XXE
Ataques de XML eXternal Entity (XXE) permitem que um documento malicioso leia arquivos locais ou acione requisições de rede. Nunca ative o carregamento de entidades em entradas que você não controla. Os padrões seguros no PHP moderno (7.0+) já desativam o carregamento de entidades externas, então a regra é simples:
- Não passe
LIBXML_NOENTouLIBXML_DTDLOADao analisar XML não confiável. - No PHP < 8.0 você pode adicionalmente chamar
libxml_disable_entity_loader(true)como uma proteção rígida. Consultelibxml_disable_entity_loader()para detalhes (a função está obsoleta no 8.0+ porque o carregamento está desativado por padrão).
Validando Documentos XML
O libxml pode validar um documento contra um DTD ou um schema XSD. DOMDocument::schemaValidate() é a forma mais direta, e os erros de validação fluem pelo mesmo buffer:
<?php
libxml_use_internal_errors(true);
$doc = new DOMDocument();
if (!$doc->load('example.xml')) {
echo "Could not load document." . PHP_EOL;
exit;
}
if ($doc->schemaValidate('example.xsd')) {
echo "The XML document is valid." . PHP_EOL;
} else {
echo "Validation failed:" . PHP_EOL;
foreach (libxml_get_errors() as $error) {
echo " line {$error->line}: " . trim($error->message) . PHP_EOL;
}
libxml_clear_errors();
}
?>Para arquivos muito grandes, prefira o XMLReader em streaming, que valida enquanto lê sem carregar o documento inteiro na memória:
<?php
$reader = new XMLReader();
$reader->open('example.xml');
$reader->setSchema('example.xsd'); // attach the XSD before reading
$valid = true;
while ($reader->read()) {
if (!$reader->isValid()) {
$valid = false;
break;
}
}
$reader->close();
echo $valid ? "Document is valid." : "Document is not valid.";
?>Manipulando Documentos XML
Para modificar um documento, geralmente usa-se o DOM. O exemplo abaixo cria um documento na memória (para que funcione sem nenhum arquivo externo), anexa um nó e exibe o resultado:
<?php
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->formatOutput = true; // pretty-print the output
// Build a root, then add a child element with text content.
$root = $doc->createElement('catalog');
$doc->appendChild($root);
$book = $doc->createElement('book', 'Learning PHP');
$book->setAttribute('id', '42');
$root->appendChild($book);
echo $doc->saveXML();
// <?xml version="1.0" encoding="UTF-8"?>
// <catalog>
// <book id="42">Learning PHP</book>
// </catalog>
?>Ao editar um arquivo do disco, carregue-o, localize o nó de destino com getElementsByTagName(), anexe a esse nó (não ao documento, que pode conter apenas um elemento raiz) e depois salve-o com save().
Quando usar isso?
- Lendo dados de configuração ou feed (RSS/Atom, respostas SOAP, sitemaps) — analise com SimpleXML, proteja com erros internos.
- Validando uploads — rejeite documentos que falhem em
schemaValidate()antes de confiar neles. - Gerando XML para uma API ou exportação — construa com DOM para que atributos e codificação sejam tratados corretamente.
- Depurando falhas de "XML inválido" — leia
libxml_get_errors()para ver a linha e coluna exatas.
Conclusão
A extensão libxml é a base da pilha XML do PHP. O padrão que traz resultados em todos os lugares é: chamar libxml_use_internal_errors(true), analisar ou validar, depois inspecionar libxml_get_errors() e libxml_clear_errors(). A partir daí, escolha a ferramenta certa — SimpleXML para leituras rápidas, DOM para edição, XMLReader para arquivos grandes — e passe opções LIBXML_* para controlar o comportamento da análise. Mantenha o carregamento de entidades desativado para entradas não confiáveis e seu tratamento de XML será robusto e seguro.