W3docs

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:

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:

ConstanteEfeito
LIBXML_NOBLANKSRemover nós em branco (somente espaço em branco).
LIBXML_NOCDATAMesclar seções CDATA como texto simples.
LIBXML_NOERROR / LIBXML_NOWARNINGSuprimir erros / avisos.
LIBXML_COMPACTOtimização de nós pequenos para documentos grandes.
LIBXML_NOENTSubstituir 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_NOENT ou LIBXML_DTDLOAD ao 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. Consulte libxml_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.

Prática

Prática
O que a extensão PHP libxml contribui?
O que a extensão PHP libxml contribui?
Was this page helpful?