21. Traitement de documents XML
Les services web que nous avons écrits jusqu'ici échangent des données JSON. Le format XML (eXtensible Markup Language) a longtemps été le format d'échange le plus répandu, et on le rencontre encore souvent : services web SOAP, flux RSS, fichiers de configuration, documents bureautiques (un fichier [.odt] ou [.docx] est une archive de fichiers XML). PHP offre deux API pour l'exploiter :
- [SimpleXML] : une API très simple, où les éléments du document deviennent des propriétés d'objets ;
- [DOM] (Document Object Model) : l'API standard du W3C, plus complète, qui permet aussi de modifier un document. PHP 8.4 en a introduit une nouvelle version, dans l'espace de noms [Dom], conforme au standard actuel du web .
Les scripts de ce chapitre sont dans le dossier [scripts-console/xml] :
21.1. Le document étudié
Nous considérons le fichier XML [data.xml] suivant :
Un document XML est un arbre d'éléments :
- ligne 1 : le prologue, qui donne la version de XML et le codage des caractères du document ;
- lignes 3-21 : l'élément racine [tribu]. Un document XML a une racine et une seule ;
- lignes 4-12 : l'élément [enseignant], fils de [tribu]. Il a deux fils, [personne] et [section] ;
- ligne 5 : l'élément [personne] a un attribut [sexe] de valeur [M] ;
- ligne 9 : un élément peut contenir à la fois des éléments et du texte ;
- lignes 13-20 : l'élément [etudiant], de même structure que [enseignant] .
21.2. Exploitation avec SimpleXML
Nous analysons ce document avec le script [simplexml-01.php] suivant :
Commentaires
- ligne 6 : le nom du fichier XML est une constante. Le script est exécuté dans son dossier, celui de [data.xml] ;
- ligne 9 : la fonction [simplexml_load_file] charge le document et rend un objet de type [SimpleXMLElement] qui représente l'élément racine [tribu]. En cas d'erreur (fichier absent, XML mal formé), elle rend [false], ce que nous testons ligne 10 ;
- ligne 15 : affichage du document. [print_r] montre comment [SimpleXML] voit l'arbre XML ;
- ligne 17 : les éléments fils sont atteints comme des propriétés ([$xml->enseignant->personne]), les attributs comme des clés de tableau ([['sexe']]). On notera que la racine [tribu] n'apparaît pas dans le code : [$xml] est déjà cet élément ;
- ligne 19 : [$xml->enseignant->personne->nom] n'est pas une chaîne mais un objet [SimpleXMLElement]. La conversion [(string)] donne son texte. Avec [declare(strict_types=1)], il vaut mieux faire cette conversion explicitement avant de passer la valeur à une fonction qui attend une chaîne ;
- ligne 21 : la valeur de l'attribut [sexe] ;
- lignes 26-27 : [isset] permet de savoir si un élément existe. Le script PHP 7 affichait le résultat booléen avec [print], ce qui donne [1] pour [true] et une chaîne vide pour [false]. Nous utilisons [var_export], qui affiche [true] ou [false] ;
- ligne 29 : la conversion [(int)] donne la valeur entière du texte de l'élément ;
- ligne 32 : la méthode [xpath] évalue une expression XPath. L'expression [//personne] désigne tous les éléments [personne] du document, à quelque niveau qu'ils soient. On obtient un tableau de [SimpleXMLElement] .
Résultats console
- lignes 2-38 : le document XML sous la forme d'un objet de type [SimpleXMLElement]. On remarque que le texte [ceci est un commentaire] n'apparaît pas : [print_r] ne montre que les éléments et les attributs ;
- lignes 39-42 : un attribut est lui aussi un objet [SimpleXMLElement] ;
- lignes 43-48 : les valeurs lues dans le document ;
- lignes 49-50 : le parcours XPath des deux personnes .
21.3. Exploitation avec la nouvelle API DOM de PHP 8.4
Depuis PHP 8.4, l'espace de noms [Dom] propose une nouvelle API DOM : la classe [Dom\XMLDocument] pour les documents XML et [Dom\HTMLDocument] pour les documents HTML5. Elle remplace avantageusement l'ancienne classe [DOMDocument] (toujours disponible) : elle est conforme au standard DOM actuel et offre les méthodes [querySelector] et [querySelectorAll] que connaissent les développeurs JavaScript. Elles permettent de chercher des éléments avec des sélecteurs CSS.
Le script [dom-01.php] exploite le même document :
Commentaires
- ligne 7 : la classe [XMLDocument] de l'espace de noms [Dom] ;
- ligne 14 : la méthode statique [createFromFile] charge le document. Contrairement à [simplexml_load_file], elle lance une exception en cas d'erreur ;
- ligne 20 : la propriété [documentElement] est l'élément racine ; [tagName] est son nom ;
- ligne 22 : le sélecteur CSS [enseignant > personne] désigne un élément [personne] fils direct d'un élément [enseignant]. [querySelector] rend le premier élément qui convient, ou [null] s'il n'y en a pas ;
- ligne 23 : la propriété [textContent] est le texte contenu dans l'élément ;
- ligne 24 : la valeur d'un attribut ;
- ligne 27 : un élément absent donne [null] ;
- ligne 29 : tous les éléments [personne] du document ;
- ligne 31 : si l'élément [prenom] manquait, [querySelector('prenom')] rendrait [null]. L'opérateur nullsafe [?->] (PHP 8.0) rend alors [null] au lieu de provoquer une erreur, et l'opérateur [??] remplace ce [null] par ['?'] ;
- ligne 37 : l'API DOM permet aussi de modifier le document : ici, on change le texte de l'élément [section] ;
- ligne 39 : [saveXml] rend le texte XML du document, ou d'un de ses éléments s'il est passé en paramètre .
Résultats console
- ligne 16 : la modification faite par le script .
Ces deux exemples ne montrent pas toutes les possibilités de [SimpleXML] et de [DOM], mais ils nous suffisent pour écrire une nouvelle version de l'exercice d'application. La documentation de PHP les décrit en détail : SimpleXML et DOM.