Il existe de nombreuses techniques pour lire et écrire du XML avec PHP. Cet article propose trois méthodes pour lire XML : à l'aide d'une bibliothèque DOM, à l'aide d'un analyseur SAX et à l'aide d'expressions régulières. L'écriture de XML à l'aide de modèles de texte DOM et PHP est également abordée.
Lire et écrire du langage XML (Extensible Markup Language) en PHP peut sembler un peu effrayant. En fait, XML et toutes ses technologies associées peuvent faire peur, mais lire et écrire du XML en PHP ne doit pas nécessairement être une tâche effrayante. Tout d’abord, vous devez en apprendre un peu plus sur XML : ce que c’est et ce que vous pouvez en faire. Ensuite, vous devez apprendre à lire et à écrire du XML en PHP, et il existe de nombreuses façons de le faire.
Cet article fournit une brève introduction à XML, puis explique comment lire et écrire du XML avec PHP.
Qu’est-ce que XML ?
XML est un format de stockage de données. Il ne définit pas quelles données sont enregistrées ni le format des données. XML définit simplement les balises et les attributs de ces balises. Un balisage XML bien formé ressemble à ceci :
<nom>Jack Herrington</nom>
Cette balise <name> contient du texte : Jack Herrington.
Le balisage XML sans texte ressemble à ceci :
<mise sous tension/>
Il existe plusieurs façons d'écrire quelque chose en XML. Par exemple, cette balise forme le même résultat que la balise précédente :
<powerUp></powerUp>
Vous pouvez également ajouter des attributs aux balises XML. Par exemple, cette balise <name> contient les premiers et derniers attributs :
<nom premier="Jack" dernier="Herrington" />
Les caractères spéciaux peuvent également être codés en XML. Par exemple, le symbole & peut être codé comme ceci :
&
Un fichier XML contenant des balises et des attributs est bien formé s'il est formaté comme dans l'exemple, ce qui signifie que les balises sont symétriques et que les caractères sont correctement encodés. Le listing 1 est un exemple de XML bien formé.
Listing 1. Exemple de liste de livres XML
<livres>
<livre>
<auteur>Jack Herrington</auteur>
<titre>PHP Hacks</titre>
<éditeur>O'Reilly</éditeur>
</livre>
<livre>
<auteur>Jack Herrington</auteur>
<titre>Podcasting Hacks</titre>
<éditeur>O'Reilly</éditeur>
</livre>
</livres>
|
Le XML du listing 1 contient une liste de livres. La balise <books> parent contient un ensemble de balises <book>, chacune contenant des balises <author>, <title> et <publisher>.
Un document XML est correct lorsque sa structure de balisage et son contenu sont vérifiés par un fichier de schéma externe. Les fichiers de schéma peuvent être spécifiés dans différents formats. Pour cet article, tout ce dont vous avez besoin est du XML bien formé.
Si vous pensez que XML ressemble beaucoup au langage HTML (Hypertext Markup Language), vous avez raison. XML et HTML sont tous deux des langages basés sur le balisage et présentent de nombreuses similitudes. Cependant, il est important de souligner que même si un document XML peut être du HTML bien formé, tous les documents HTML ne sont pas du XML bien formé. La balise newline (br) est un bon exemple de la différence entre XML et HTML. Cette balise de nouvelle ligne est du HTML bien formé, mais pas du XML bien formé :
<p>Ceci est un paragraphe<br>
Avec un saut de ligne</p>
Cette balise de nouvelle ligne est en XML et HTML bien formé :
<p>Ceci est un paragraphe<br />
Avec un saut de ligne</p>
Si vous souhaitez écrire du HTML au format XML bien formé, suivez la norme XHTML (Extensible Hypertext Markup Language) du comité W3C (voir Ressources ). Tous les navigateurs modernes peuvent afficher le XHTML. De plus, vous pouvez utiliser des outils XML pour lire du XHTML et rechercher les données dans le document, ce qui est beaucoup plus simple que d'analyser du HTML.
Lire XML à l'aide de la bibliothèque DOM
Le moyen le plus simple de lire des fichiers XML bien formés consiste à utiliser la bibliothèque Document Object Model (DOM) compilée dans certaines installations PHP. La bibliothèque DOM lit l'intégralité du document XML en mémoire et le représente sous la forme d'une arborescence de nœuds, comme le montre la figure 1.
Figure 1. Arborescence XML DOM pour le livre XML
Le nœud books en haut de l’arborescence comporte deux balises enfants book. Dans chaque livre, il y a plusieurs nœuds : auteur, éditeur et titre. Les nœuds auteur, éditeur et titre ont chacun des nœuds enfants de texte qui contiennent du texte.
Le code qui lit le fichier XML du livre et affiche le contenu à l'aide du DOM est présenté dans le listing 2.
Listing 2. Lecture du XML d'un livre à l'aide de DOM
<?php
$doc = nouveau DOMDocument();
$doc->load( 'books.xml' );
$livres = $doc->getElementsByTagName( "livre" );
foreach( $books comme $book )
{
$authors = $book->getElementsByTagName( "auteur" );
$auteur = $auteurs->item(0)->nodeValue ;
$publishers = $book->getElementsByTagName( "éditeur" );
$publisher = $publishers->item(0)->nodeValue ;
$titles = $book->getElementsByTagName( "titre" );
$titre = $titres->item(0)->nodeValue ;
echo "$titre - $auteur - $éditeurn";
}
?>
|
Le script crée d'abord un nouvel objet DOMdocument et charge le livre XML dans cet objet à l'aide de la méthode de chargement. Ensuite, le script utilise la méthode getElementsByName pour obtenir une liste de tous les éléments sous le nom spécifié.
Dans la boucle du nœud book, le script utilise la méthode getElementsByName pour obtenir la nodeValue des balises auteur, éditeur et titre. nodeValue est le texte du nœud. Le script affiche ensuite ces valeurs.
Vous pouvez exécuter des scripts PHP sur la ligne de commande comme ceci :
%phpe1.php
Hacks PHP - Jack Herrington - O'Reilly
Astuces de podcasting - Jack Herrington - O'Reilly
%
Comme vous pouvez le voir, chaque bloc de livre génère une ligne. C'est un bon début. Mais que se passe-t-il si vous n'avez pas accès à la bibliothèque XML DOM ?
Lire XML avec l'analyseur SAX
Une autre façon de lire XML consiste à utiliser un analyseur XML Simple API (SAX). La plupart des installations de PHP incluent un analyseur SAX. L'analyseur SAX fonctionne sur un modèle de rappel. Chaque fois qu'une balise est ouverte ou fermée, ou chaque fois que l'analyseur voit du texte, la fonction définie par l'utilisateur est rappelée avec des informations sur le nœud ou le texte.
L'avantage de l'analyseur SAX est qu'il est vraiment léger. L'analyseur ne conserve pas le contenu en mémoire pendant de longues périodes, il peut donc être utilisé pour des fichiers très volumineux. L'inconvénient est que l'écriture des rappels de l'analyseur SAX est très fastidieuse. Le listing 3 montre le code qui utilise SAX pour lire un fichier XML de livre et afficher le contenu.
Listing 3. Lecture du livre XML avec l'analyseur SAX
<?php
$g_books = tableau();
$g_elem = nul ;
fonction startElement( $parser, $name, $attrs )
{
global $g_books, $g_elem ;
if ( $name == 'BOOK' ) $g_books []= array();
$g_elem = $nom;
}
fonction endElement( $parser, $name )
{
global $g_elem;
$g_elem = nul ;
}
fonction textData( $parser, $text )
{
global $g_books, $g_elem ;
if ( $g_elem == 'AUTEUR' ||
$g_elem == 'ÉDITEUR' ||
$g_elem == 'TITRE' )
{
$g_books[ count( $g_books ) - 1 ][ $g_elem ] = $text;
}
}
$parser = xml_parser_create();
xml_set_element_handler( $parser, "startElement", "endElement" );
xml_set_character_data_handler( $parser, "textData" );
$f = fopen( 'books.xml', 'r' );
tandis que( $data = fread( $f, 4096 ) )
{
xml_parse( $parser, $data );
}
xml_parser_free( $parser );
foreach( $g_books comme $book )
{
echo $book['TITRE']." - ".$book['AUTEUR']." - ";
echo $book['PUBLISHER']."n";
}
?>
|
Le script configure d'abord le tableau g_books, qui contient tous les livres et informations sur les livres en mémoire, et la variable g_elem contient le nom de la balise que le script est en train de traiter. Le script définit ensuite la fonction de rappel. Dans cet exemple, les fonctions de rappel sont startElement, endElement et textData. Lors de l'ouverture et de la fermeture de la marque, appelez respectivement les fonctions startElement et endElement. TextData est appelé sur le texte entre les balises d'ouverture et de fermeture.
Dans cet exemple, la balise startElement recherche la balise book pour démarrer un nouvel élément dans le tableau book. La fonction textData examine ensuite l'élément actuel pour voir s'il s'agit d'une balise d'éditeur, de titre ou d'auteur. Si tel est le cas, la fonction place le texte actuel dans le livre actuel.
Pour permettre la poursuite de l'analyse, le script crée un analyseur à l'aide de la fonction xml_parser_create. Ensuite, définissez la poignée de rappel. Ensuite, le script lit le fichier et envoie des morceaux du fichier à l'analyseur. Une fois le fichier lu, la fonction xml_parser_free supprime l'analyseur. La fin du script affiche le contenu du tableau g_books.
Comme vous pouvez le constater, c'est beaucoup plus difficile que d'écrire la même fonctionnalité dans le DOM. Que se passe-t-il s'il n'y a ni bibliothèque DOM ni bibliothèque SAX ? Existe-t-il des alternatives ?
Analyser XML avec des expressions régulières
Je suis sûr que certains ingénieurs me reprocheront même d'avoir mentionné cette méthode, mais il est possible d'analyser XML avec des expressions régulières. Le listing 4 montre un exemple d'utilisation de la fonction preg_ pour lire un fichier livre.
Listing 4. Lire XML avec des expressions régulières
<?php
$xml = "";
$f = fopen( 'books.xml', 'r' );
while( $data = fread( $f, 4096 ) ) { $xml .= $data }
fclose( $f );
preg_match_all( "/<livre>(.*?)</livre>/s",
$xml, $bookblocks );
foreach( $bookblocks[1] comme $block )
{
preg_match_all( "/<auteur>(.*?)</auteur>/",
$bloc, $auteur );
preg_match_all( "/<titre>(.*?)</titre>/",
$bloc, $titre );
preg_match_all( "/<éditeur>(.*?)</éditeur>/",
$bloc, $éditeur );
echo( $titre[1][0]." - ".$auteur[1][0]." - ".
$publisher[1][0]."n" );
}
?>
|
Remarquez à quel point ce code est court. Initialement, il lit le fichier dans une grande chaîne. Utilisez ensuite une fonction regex pour lire chaque élément du livre. Enfin, utilisez une boucle foreach pour parcourir chaque bloc de livre et extraire l'auteur, le titre et l'éditeur.
Alors, où sont les défauts ? Le problème avec l'utilisation du code d'expression régulière pour lire du XML est qu'il ne vérifie pas d'abord que le XML est bien formé. Cela signifie qu'il n'y a aucun moyen de savoir si le XML est bien formé avant de le lire. De plus, certains fichiers XML bien formés peuvent ne pas correspondre à l'expression régulière et doivent donc être modifiés ultérieurement.
Je ne recommande jamais d'utiliser des expressions régulières pour lire du XML, mais c'est parfois le meilleur moyen d'assurer la compatibilité car les fonctions d'expression régulière sont toujours disponibles. N'utilisez pas d'expressions régulières pour lire du XML directement auprès de l'utilisateur, car vous n'avez aucun contrôle sur le format ou la structure de ce XML. Vous devez toujours utiliser une bibliothèque DOM ou un analyseur SAX pour lire le XML de l'utilisateur. Écrire du XML à l'aide de DOM
La lecture de XML n'est qu'une partie de l'équation. Comment écrire du XML ? La meilleure façon d'écrire du XML est d'utiliser le DOM. Le listing 5 montre comment le DOM construit le fichier XML du livre.
Listing 5. Écrire un livre XML en utilisant DOM
<?php
$livres = tableau();
$livres [] = tableau(
'titre' => 'Hacks PHP',
'auteur' => 'Jack Herrington',
'éditeur' => "O'Reilly"
);
$livres [] = tableau(
'title' => 'Podcasting Hacks',
'auteur' => 'Jack Herrington',
'éditeur' => "O'Reilly"
);
$doc = nouveau DOMDocument();
$doc->formatOutput = true ;
$r = $doc->createElement( "livres" );
$doc->appendChild( $r );
foreach( $books comme $book )
{
$b = $doc->createElement( "livre" );
$auteur = $doc->createElement( "auteur" );
$auteur->appendChild(
$doc->createTextNode( $book['auteur'] )
);
$b->appendChild( $auteur );
$titre = $doc->createElement( "titre" );
$titre->appendChild(
$doc->createTextNode( $book['title'] )
);
$b->appendChild( $titre );
$publisher = $doc->createElement( "éditeur" );
$publisher->appendChild(
$doc->createTextNode( $book['publisher'] )
);
$b->appendChild( $publisher );
$r->appendChild( $b );
}
echo $doc->saveXML();
?>
|
En haut du script, le tableau books est chargé avec quelques exemples de livres. Ces données peuvent provenir de l'utilisateur ou de la base de données.
Une fois les exemples de livres chargés, le script crée un nouveau DOMDocument et y ajoute le nœud racine des livres. Le script crée ensuite des nœuds pour l'auteur, le titre et l'éditeur de chaque livre, et ajoute des nœuds de texte à chaque nœud. La dernière étape pour chaque nœud de livre consiste à le rajouter aux livres du nœud racine.
À la fin du script, utilisez la méthode saveXML pour afficher le XML sur la console. (Vous pouvez également utiliser la méthode save pour créer un fichier XML.) La sortie du script est présentée dans le listing 6.
Listing 6. Sortie du script de build DOM
%phpe4.php
<?version XML="1.0"?>
<livres>
<livre>
<auteur>Jack Herrington</auteur>
<titre>PHP Hacks</titre>
<éditeur>O'Reilly</éditeur>
</livre>
<livre>
<auteur>Jack Herrington</auteur>
<titre>Podcasting Hacks</titre>
<éditeur>O'Reilly</éditeur>
</livre>
</livres>
%
|
La véritable valeur de l’utilisation du DOM est que le XML qu’il crée est toujours bien formé. Mais que se passe-t-il si vous ne parvenez pas à créer du XML à l'aide du DOM ?
Écrire du XML en PHP
Si le DOM n'est pas disponible, XML peut être écrit à l'aide des modèles de texte PHP. Le listing 7 montre comment PHP construit le fichier XML du livre.
Listing 7. Rédaction d'un livre XML en PHP
<?php
$livres = tableau();
$livres [] = tableau(
'title' => 'PHP Hacks',
'auteur' => 'Jack Herrington',
'éditeur' => "O'Reilly"
);
$livres [] = tableau(
'title' => 'Podcasting Hacks',
'auteur' => 'Jack Herrington',
'éditeur' => "O'Reilly"
);
?>
<livres>
<?php
foreach( $books comme $book )
{
?>
<livre>
<titre><?php echo( $book['titre'] );
<auteur><?php echo( $book['auteur'] );
</auteur>
<éditeur><?php echo( $book['éditeur'] );
</éditeur>
</livre>
<?php
}
?>
</livres>
|
La partie supérieure du script est similaire à un script DOM. Le bas du script ouvre la balise books, puis parcourt chaque livre, créant la balise book et toutes les balises internes de titre, d'auteur et d'éditeur.
Le problème avec cette approche est le codage des entités. Pour garantir que les entités sont correctement codées, la fonction htmlentities doit être appelée sur chaque élément, comme indiqué dans le listing 8.
Listing 8. Encodage des entités à l'aide de la fonction htmlentities
<livres>
<?php
foreach( $books comme $book )
{
$title = htmlentities( $book['title'], ENT_QUOTES );
$auteur = htmlentities( $book['auteur'], ENT_QUOTES );
$publisher = htmlentities( $book['publisher'], ENT_QUOTES );
?>
<livre>
<titre><?php echo( $titre );
<auteur><?php echo( $auteur );> </auteur>
<éditeur><?php echo( $éditeur );
</éditeur>
</livre>
<?php
}
?>
</livres>
|
C'est là qu'écrire du XML en PHP de base devient ennuyeux. Vous pensez avoir créé un XML parfait, mais dès que vous essayez d'utiliser les données, vous découvrez que certains éléments sont mal encodés.
Conclusion
Il y a toujours beaucoup d'exagération et de confusion autour du XML. Cependant, ce n'est pas aussi difficile qu'on le pense, surtout dans un langage aussi performant que PHP. Une fois que vous aurez compris et implémenté correctement XML, vous disposerez de nombreux outils puissants. XPath et XSLT sont deux de ces outils qui méritent d'être étudiés.