PHP XML DOM
Aprenda a usar a extensão DOM do PHP para carregar, criar, modificar, consultar (com XPath) e salvar documentos XML, com exemplos executáveis.
Para que serve a extensão DOM
A extensão DOM (Document Object Model) representa um documento XML como uma árvore de nós em memória. Cada elemento, atributo, fragmento de texto e comentário é um objeto nó que você pode ler, mover, adicionar ou excluir. Como o documento inteiro é carregado na RAM, o DOM é a ferramenta certa quando você precisa modificar XML, construir um documento do zero ou executar consultas XPath que percorrem a árvore.
Esta página cobre como carregar, criar, modificar, consultar e salvar XML com DOMDocument. As diferenças em relação às alternativas mais leves são:
- Use a extensão SimpleXML quando precisar apenas ler XML bem formado rapidamente com código mínimo.
- Use o XML Parser (Expat) para processamento em fluxo baseado em eventos de arquivos muito grandes que não devem ser mantidos totalmente na memória.
- Recorra ao DOM (esta página) quando precisar de controle total de leitura/escrita e XPath.
O DOM e o libxml compartilham um sistema de erros; consulte PHP libxml para gerenciar erros de análise.
Habilitando a extensão
A extensão DOM é fornecida com o PHP e está habilitada por padrão na maioria das compilações (faz parte do pacote php-xml no Debian/Ubuntu). Você pode confirmar que está disponível:
<?php
var_dump(extension_loaded('dom')); // bool(true)Se ela estiver ausente, instale o pacote php-xml para sua plataforma, ou habilite extension=dom no php.ini e reinicie o servidor web.
Carregando um documento XML
Crie um DOMDocument e carregue XML a partir de uma string com loadXML() ou de um arquivo com load(). Ative libxml_use_internal_errors(true) primeiro para que marcações malformadas não gerem avisos — você mesmo coleta os erros.
<?php
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="1"><title>PHP for Beginners</title></book>
<book id="2"><title>Advanced XML</title></book>
</books>
XML;
libxml_use_internal_errors(true);
$doc = new DOMDocument();
if (!$doc->loadXML($xml)) {
foreach (libxml_get_errors() as $error) {
echo trim($error->message) . "\n";
}
libxml_clear_errors();
exit;
}
$root = $doc->documentElement;
echo "Root element: {$root->nodeName}\n";
foreach ($root->getElementsByTagName('title') as $title) {
echo "Title: {$title->nodeValue}\n";
}Saída:
Root element: books
Title: PHP for Beginners
Title: Advanced XMLgetElementsByTagName() retorna um DOMNodeList ativo que você pode percorrer diretamente com foreach — geralmente é mais claro do que percorrer childNodes, que também inclui os nós de texto de espaço em branco entre os elementos.
Criando um documento XML do zero
Construa um documento criando nós no DOMDocument e os anexando a um pai. Defina formatOutput = true para obter uma saída indentada e legível de saveXML().
<?php
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->formatOutput = true;
$root = $doc->createElement('books');
$doc->appendChild($root);
$book = $doc->createElement('book');
$book->setAttribute('id', '1');
$root->appendChild($book);
$title = $doc->createElement('title', 'PHP for Beginners');
$book->appendChild($title);
echo $doc->saveXML();Saída:
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="1">
<title>PHP for Beginners</title>
</book>
</books>Principais métodos utilizados aqui:
createElement($name, $value)— cria um elemento, opcionalmente com conteúdo de texto.setAttribute($name, $value)— adiciona ou sobrescreve um atributo em um elemento.appendChild($node)— anexa um nó como o último filho de seu pai.
Atenção: passar texto diretamente para
createElement('title', $userInput)não escapa&,<ou>de forma confiável. Para texto não confiável, adicione um nó de texto em vez disso:$el->appendChild($doc->createTextNode($userInput)), que sempre escapa caracteres especiais.
Modificando e excluindo nós
Como toda a árvore está em memória, você pode alterar texto, atualizar atributos e remover elementos antes de salvar. Uma maneira limpa de localizar o nó correto é com XPath (abordado a seguir), mas aqui o usamos diretamente:
<?php
$xml = <<<XML
<books>
<book id="1"><title>PHP for Beginners</title></book>
<book id="2"><title>Advanced XML</title></book>
</books>
XML;
$doc = new DOMDocument();
$doc->formatOutput = true;
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
// Rename the first title
$first = $xpath->query('//book[@id="1"]/title')->item(0);
$first->nodeValue = 'PHP Essentials';
// Remove the second book
$second = $xpath->query('//book[@id="2"]')->item(0);
$second->parentNode->removeChild($second);
echo $doc->saveXML();Saída:
<?xml version="1.0"?>
<books>
<book id="1"><title>PHP Essentials</title></book>
</books>Para excluir um nó, você chama removeChild() em seu pai, por isso $second->parentNode->removeChild($second) é o idioma utilizado. Atribuir a nodeValue substitui o conteúdo de texto de um elemento.
Consultando com XPath
DOMXPath permite selecionar nós com expressões de caminho em vez de percorrer a árvore manualmente — muito mais conciso do que loops aninhados.
<?php
$xml = <<<XML
<books>
<book id="1"><title>PHP for Beginners</title></book>
<book id="2"><title>Advanced XML</title></book>
</books>
XML;
$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
// Every <title> anywhere in the document
foreach ($xpath->query('//title') as $node) {
echo $node->nodeValue . "\n";
}
// The title of the book whose id is "2"
$result = $xpath->query('//book[@id="2"]/title');
echo "Book 2: " . $result->item(0)->nodeValue . "\n";Saída:
PHP for Beginners
Advanced XML
Book 2: Advanced XMLPadrões XPath comuns:
| Expressão | Seleciona |
|---|---|
//title | Todos os elementos <title> em qualquer profundidade |
/books/book | Filhos <book> diretamente sob a raiz <books> |
//book[@id="2"] | Elementos <book> com atributo id="2" |
//book/@id | Os nós de atributo id de cada <book> |
//book[1] | O primeiro <book> (índices XPath começam em 1) |
Salvando em um arquivo
Persista a árvore em memória com save(), que retorna false em caso de falha (por exemplo, um diretório sem permissão de escrita).
<?php
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->formatOutput = true;
$root = $doc->createElement('config');
$doc->appendChild($root);
$root->appendChild($doc->createElement('debug', 'false'));
if ($doc->save(__DIR__ . '/output.xml')) {
echo 'Saved successfully.';
} else {
echo 'Failed to save — check directory permissions.';
}Use saveXML() (sem argumentos) quando quiser o XML como uma string — útil para retorná-lo de uma API ou exibi-lo em uma resposta.
Resumo
DOMDocumentcarrega um documento XML inteiro em uma árvore mutável de nós.- Use
loadXML()/load()para ler,createElement()eappendChild()para construir, eremoveChild()para excluir. DOMXPath::query()seleciona nós com expressões de caminho concisas.save()grava em um arquivo;saveXML()retorna o documento como uma string.- Escolha o DOM quando precisar escrever ou consultar XML; escolha o SimpleXML para leituras rápidas e o XML Parser para transmitir arquivos enormes.