xpath()
Apprenez à utiliser SimpleXMLElement::xpath() en PHP pour interroger des documents XML avec des expressions XPath, filtrer des nœuds et gérer les espaces de noms.
Introduction
SimpleXMLElement::xpath() exécute une requête XPath sur un document XML chargé avec l'extension SimpleXML de PHP et retourne les nœuds correspondants. Sans cette méthode, vous ne pouvez parcourir un arbre XML que propriété par propriété ($xml->book->title) ; avec elle, vous pouvez accéder directement à n'importe quel nœud — quelle que soit sa profondeur — grâce à une seule expression de chemin comme //book/title.
Cette page explique ce que retourne xpath(), la syntaxe XPath la plus courante, comment lire les attributs et gérer les espaces de noms, ainsi que les pièges à éviter.
Syntaxe
public SimpleXMLElement::xpath(string $expression): array|false$expression— l'expression XPath à évaluer, relative au nœud sur lequel vous l'appelez.- Retourne — un array d'objets
SimpleXMLElementpour chaque nœud correspondant, un array vide si rien ne correspond, oufalseen cas d'expression malformée.
Le résultat étant toujours un array, vous l'itérez généralement avec foreach, même si vous attendez un seul résultat.
Premier exemple
Les exemples ci-dessous utilisent simplexml_load_string() afin de fonctionner tels quels, sans fichier externe :
<?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";
}Sortie :
The Pragmatic Programmer
PHP Cookbook//title signifie « tout élément title à n'importe quelle profondeur ». La boucle affiche chaque résultat ; convertir un SimpleXMLElement en string (fait implicitement par echo) produit son contenu textuel.
Expressions XPath courantes
| Expression | Sélectionne |
|---|---|
/library/book | les éléments book enfants directs de la racine library |
//book | tout élément book, à n'importe quelle profondeur |
//book/title | l'enfant title de chaque book |
//book[1] | le premier book (XPath est indexé à 1, pas 0) |
//book[@genre='fiction'] | les livres dont l'attribut genre vaut fiction |
//book[author='Sklar'] | les livres ayant un enfant <author> égal à Sklar |
//@genre | tout nœud d'attribut genre |
Filtrage avec un prédicat
Un prédicat entre crochets conserve uniquement les nœuds qui satisfont une condition :
<?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 matchSortie :
Dune
1 matchLa lecture d'un attribut dans le prédicat utilise @, tandis que la lecture depuis un nœud résultat utilise la syntaxe tableau — (string) $book['genre']. Consultez attributes pour une vue d'ensemble complète.
Travailler avec les espaces de noms XML
Si le document déclare des espaces de noms, un chemin simple comme //book ne retournera rien — l'analyseur a besoin du préfixe d'espace de noms. Enregistrez un préfixe avec registerXPathNamespace() d'abord, puis utilisez-le dans l'expression :
<?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
}Sortie :
Clean CodeLe préfixe que vous enregistrez (l) est local à votre requête — il n'a pas besoin de correspondre au préfixe utilisé dans le document (lib) ; seul l'URI d'espace de noms doit correspondre.
Pièges courants
- Vérifiez toujours le résultat.
xpath()retournefalsepour une expression invalide et un array vide si rien ne correspond.foreach (($xml->xpath($e) ?: []) as $n)protège contre les deux cas. - Les résultats sont des objets, pas des strings. Convertissez avec
(string)quand vous avez besoin du texte :(string) $node. - XPath indexe à partir de 1.
//book[1]est le premier livre ; il n'y a pas de[0]. - Le contexte compte. Appeler
xpath('title')sur un nœudbookeffectue la recherche relativement à ce nœud, tandis qu'un/ou//initial recherche depuis la racine du document, quel que soit l'endroit où vous l'appelez.
Conclusion
SimpleXMLElement::xpath() transforme un parcours d'arbre profond et répétitif en une seule requête déclarative. Combiné avec des prédicats et l'enregistrement d'espaces de noms, il vous permet de cibler précisément les nœuds dont vous avez besoin. Associez-le à simplexml_load_string() ou à l'API SimpleXML plus complète pour lire et transformer du XML en quelques lignes seulement.