xpath()
A função SimpleXMLElement::xpath() executa consultas XPath em documentos XML com a extensão SimpleXML do PHP e retorna os nós correspondentes.
Introdução
SimpleXMLElement::xpath() executa uma consulta XPath em um documento XML carregado com a extensão SimpleXML do PHP e retorna os nós correspondentes. Sem ela, você só consegue percorrer uma árvore XML propriedade a propriedade ($xml->book->title); com ela, você pode ir diretamente a qualquer nó — independentemente de quão profundo esteja — usando uma única expressão de caminho como //book/title.
Esta página explica o que xpath() retorna, a sintaxe XPath mais usada, como ler atributos e lidar com namespaces, além dos erros comuns que costumam pegar as pessoas de surpresa.
Sintaxe
public SimpleXMLElement::xpath(string $expression): array|false$expression— a expressão XPath a ser avaliada, relativa ao nó em que você a chama.- Retorna — um array de objetos
SimpleXMLElementpara cada nó correspondente, um array vazio quando nada corresponde, oufalseem caso de expressão inválida.
Como o resultado é sempre um array, normalmente você o itera com foreach, mesmo quando espera apenas uma correspondência.
Um primeiro exemplo
Os exemplos abaixo usam simplexml_load_string() para que funcionem diretamente, sem nenhum arquivo externo:
<?php
$data = <<<XML
<library>
<book genre="fiction">
<title>The Pragmatic Programmer</title>
<author>Hunt</author>
</book>
<book genre="reference">
<title>PHP Cookbook</title>
<author>Sklar</author>
</book>
</library>
XML;
$xml = simplexml_load_string($data);
// Select every <title> anywhere under the root.
foreach ($xml->xpath('//title') as $title) {
echo $title . "\n";
}Saída:
The Pragmatic Programmer
PHP Cookbook//title significa "qualquer elemento title em qualquer profundidade." O laço imprime cada resultado; converter um SimpleXMLElement para string (feito implicitamente pelo echo) retorna seu conteúdo de texto.
Expressões XPath comuns
| Expressão | Seleciona |
|---|---|
/library/book | elementos book que são filhos diretos do elemento raiz library |
//book | todos os elementos book, em qualquer profundidade |
//book/title | o filho title de cada book |
//book[1] | o primeiro book (XPath é indexado a partir de 1, não de 0) |
//book[@genre='fiction'] | livros cujo atributo genre é igual a fiction |
//book[author='Sklar'] | livros com um filho <author> igual a Sklar |
//@genre | todos os nós de atributo genre |
Filtrando com um predicado
Um predicado entre colchetes mantém apenas os nós que satisfazem uma condição:
<?php
$data = <<<XML
<library>
<book genre="fiction"><title>Dune</title></book>
<book genre="reference"><title>PHP Cookbook</title></book>
</library>
XML;
$xml = simplexml_load_string($data);
$fiction = $xml->xpath("//book[@genre='fiction']");
echo $fiction[0]->title . "\n"; // Dune
echo count($fiction) . " match\n"; // 1 matchSaída:
Dune
1 matchLer um atributo dentro do predicado usa @, enquanto lê-lo de um nó de resultado usa sintaxe de array — (string) $book['genre']. Veja atributos para o panorama completo.
Trabalhando com namespaces XML
Se o documento declara namespaces, um caminho simples como //book não retornará nada — o parser precisa do prefixo de namespace. Registre um prefixo com registerXPathNamespace() primeiro e, em seguida, use-o na expressão:
<?php
$data = <<<XML
<lib:library xmlns:lib="http://example.com/lib">
<lib:book><lib:title>Clean Code</lib:title></lib:book>
</lib:library>
XML;
$xml = simplexml_load_string($data);
$xml->registerXPathNamespace('l', 'http://example.com/lib');
foreach ($xml->xpath('//l:book/l:title') as $title) {
echo $title . "\n"; // Clean Code
}Saída:
Clean CodeO prefixo que você registra (l) é local para sua consulta — ele não precisa corresponder ao prefixo usado no documento (lib); apenas o URI do namespace precisa ser igual.
Armadilhas comuns
- Sempre verifique o resultado.
xpath()retornafalseem uma expressão inválida e um array vazio quando não há correspondência.foreach (($xml->xpath($e) ?: []) as $n)protege contra os dois casos. - Os resultados são objetos, não strings. Converta com
(string)quando precisar do texto:(string) $node. - XPath indexa a partir de 1.
//book[1]é o primeiro livro; não existe[0]. - O contexto importa. Chamar
xpath('title')em um nóbookpesquisa relativo a esse nó, enquanto um/ou//inicial pesquisa a partir da raiz do documento, independentemente de onde você o chama.
Conclusão
SimpleXMLElement::xpath() transforma a navegação profunda e repetitiva na árvore em uma única consulta declarativa. Combinado com predicados e registro de namespaces, permite identificar exatamente os nós que você precisa. Use-o com simplexml_load_string() ou com a API mais ampla do SimpleXML para ler e transformar XML em apenas algumas linhas.