Manipuler XML avec PHP

Le format XML est utilisé de façon très variée. Nous le trouvons dans des services Web, des fichiers de configuration, des formats comme SVG, MathML, docx, odt, etc. Sa manipulation dans un langage comme PHP est donc particulièrement importante.

On peut manipuler XML de différentes manières

  • A la main

  • Avec XMLWriter/XMLReader

  • Avec DOM

  • Avec SimpleXML

ou des combinaisons de ces méthodes.

  • DOM ou Document Object Model est une méthode qui recrée toute l’arborescence d’un document XML sous forme d’objets PHP. Son utilisation est simple mais elle est couteuse en ressources, en temps d’exécution et un peu verbeuse.

  • XMLWriter et XMLReader traitent les fichiers XML a plus bas niveau mais leur utilisation exclusive rend parfois le code délicat à implémenter surtout pour la lecture de fichiers complexes.

  • SimpleXML représente une sorte de compromis Simplicité/Performance.

  • Traiter des fichiers xml « à la main » est généralement à éviter sauf pour créer des fichiers très simples.

Traitement de fichiers XML à la main:

Observons d’abord comment créer un fichier XML contenant une liste de programmes TV: La lecture de fichiers XML sans API est peu recommandée.

<?php 
header('Content-Type: text/xml');
print '<?xml version="1.0"?>' . "\n";
print "<programmes>\n";
$programmes = array(
    array('nom'=> 'Simpsons',
        'chaine'=> 'TF18', 
        'debut' => '21:00',
        'duree' => '30'),
    array('nom'=> 'Blake et Mortimer',
        'chaine' => 'M54',
        'debut'=>'20:00','duree'=>'60'));
foreach ($programmes as $show) {
    print "\t<show>\n";
    foreach($show as $tag => $data) {
      print "\t<$tag>"
      . htmlspecialchars($data)
      . "\t</$tag>\n";
    }
    print "</show>\n";}
print "</programmes>\n";  

Exécution :

Ecriture XML à la main

Resultat brut html :

<?xml version="1.0"?>
<programmes>
	<show>
	<nom>Simpsons	</nom>
	<chaine>TF18	</chaine>
	<debut>21:00	</debut>
	<duree>30	</duree>
</show>
	<show>
	<nom>Blake et Mortimer	</nom>
	<chaine>M54	</chaine>
	<debut>20:00	</debut>
	<duree>60	</duree>
</show>
</programmes>

Ecriture avec XMLWriter:

Un exemple simple pour démarrer:

<?php
$xml = new XMLWriter();
$xml->openURI('test.xml');
$xml->startElement('toto');
$xml->writeElement('url', 'http://totototo.com');
$xml->endElement();
$xml->flush();

Resultat brut :

<toto><url>http://toto.com</url></toto>

et si on récupère des données de la table CARNET pour les exporter en XML:

<?php
require_once('connexion.php');
$connexion=connect_bd();
$sql="SELECT * from CARNET";
$data=$connexion->query($sql);
$xml= new XMLWriter();
$xml->openUri("contacts.xml");
$xml->startDocument('1.0', 'utf-8');
$xml->startElement('mescontacts');

  while($pers=$data->fetch()){
    $xml->startElement('contact');
    $xml->writeAttribute('id', $pers['ID']);
    $xml->writeElement('prenom',$pers['PRENOM']);
    $xml->writeElement('nom',$pers['NOM']);
    $xml->writeElement('naissance',$pers['NAISSANCE']);
    $xml->endElement();
  }
$xml->endElement();
$xml->endElement();
$xml->flush();

Resultat :

<?xml version="1.0" encoding="UTF-8"?>
<mescontacts>
    <contact id="1">
        <prenom>JOHN</prenom>
        <nom>SMITH</nom>
        <naissance>1980-12-17</naissance>
    </contact>
    <contact id="2">
        <prenom>JEAN</prenom>
        <nom>DURAND</nom>
        <naissance>1983-01-13</naissance>
    </contact>
    <contact id="3">
        <prenom>JEANNE</prenom>
        <nom>GUDULE</nom>
        <naissance>1967-11-06</naissance>
        </contact>
    <contact id="4">
        <prenom>EMILIO</prenom>
        <nom>ZAPATA</nom>
        <naissance>1956-12-01</naissance>
        </contact>
    <contact id="5">
        <prenom>NICOLAS</prenom>
        <nom>JOURDAIN</nom>
        <naissance>2000-09-10</naissance>
        </contact>
    <contact id="6">
        <prenom>MARIE</prenom>
        <nom>DUPUY</nom>
        <naissance>1986-01-11</naissance>
    </contact>
    <contact id="7">
        <prenom>LOU</prenom>
        <nom>ANDREAS</nom>
        <naissance>1861-02-12</naissance>
    </contact>
    <contact id="9">
        <prenom>Franz</prenom>
        <nom>Kafka</nom>
        <naissance>1883-07-03</naissance>
        </contact>
    <contact id="11">
        <prenom>Joe</prenom>
        <nom>Dalton</nom>
        <naissance>2003-12-06</naissance>
        </contact>
    </mescontacts>

Traitements avec DOM:

Ecriture de fichier XML avec DOM en utilisant des données provenant d’une Base de Données. Partons de la table films suivante:

CREATE TABLE IF NOT EXISTS `films` (
 `code_film` int(11) NOT NULL AUTO_INCREMENT,
 `titre_original` varchar(50) DEFAULT NULL,
 `titre_francais` varchar(50) DEFAULT NULL,
 `pays` varchar(20) DEFAULT NULL,
 `date` int(11) DEFAULT NULL,
 `duree` int(11) DEFAULT NULL,
 `couleur` varchar(10) DEFAULT NULL,
 `realisateur` int(11) DEFAULT NULL,
 `image` varchar(20) DEFAULT NULL,
 PRIMARY KEY(`code_film`)
)

et créons un fichier XML avec les données de cette table en utilisant DOM:

<?php
// avec le fichier connexion.php utilisé auparavant
require("connexion.php");
$connexion=connect_bd();
$sql="SELECT * from films limit 10";
$data=$connexion->query($sql);
if ($data){ 
$document = new DomDocument();
$document->preserveWhiteSpace = false;
$document->formatOutput = true;
// on crée la racine <lesfilms> et on l'insère dans le document
$lesfilms = $document->createElement('lesfilms');
$document->appendChild($lesfilms);

// On boucle  pour tous les films trouvés dans la BD:
while($unfilm=$data->fetch(PDO::FETCH_OBJ))
    {
    $film=$document->createElement('film');
    $film->setAttribute('idreal', $unfilm->realisateur);
    $lesfilms->appendChild($film);
    // on crée l'élément title et on l'ajoute à $film
    $title = $document->createElement('titre');
    $film->appendChild($title);
    // on définit le texte pour $title
    $text=$document->createTextNode(utf8_encode($unfilm->titre_original));
    $title->appendChild($text);
    
    //crée et ajoute le realisateur a $film
    $realisateur=$document->createElement('date');
    $id=$document->createTextNode($unfilm->date);
    $realisateur->appendChild($id);
    $film->appendChild($realisateur);
  }
  $document->save('myFilms.xml');
  echo "Export XML fini !";
 }

 else { echo "Aucun film dans la base !" ;}

Exécution :

Creation XML avec DOM

Resultat :

<?xml version="1.0"?>
<lesfilms>
  <film idreal="7">
    <titre>Pandora and the flying Dutchman                   </titre>
    <date>1951</date>
  </film>
  <film idreal="8">
    <titre>Johnny Guitar                                     </titre>
    <date>1954</date>
  </film>
  <film idreal="9">
    <titre>Woman under the Influence (A)                     </titre>
    <date>1974</date>
  </film>
  <film idreal="10">
    <titre>Apartment (The)                                   </titre>
    <date>1960</date>
  </film>
  <film idreal="11">
    <titre>Victor/Victoria                                   </titre>
    <date>1982</date>
  </film>
  <film idreal="12">
    <titre>Modern Times                                      </titre>
    <date>1936</date>
  </film>
  <film idreal="13">
    <titre>M&#xC3;&#xA9;pris (Le)                                       </titre>
    <date>1963</date>
  </film>
  <film idreal="14">
    <titre>Jour de f&#xC3;&#xAA;te                                      </titre>
    <date>1948</date>
  </film>
  <film idreal="15">
    <titre>Olvidados (Los)                                   </titre>
    <date>1950</date>
  </film>
  <film idreal="16">
    <titre>West Side Story                                   </titre>
    <date>1961</date>
  </film>
</lesfilms>

Relecture avec SimpleXML:

<?php

$lesfilms = simplexml_load_file('myFilms.xml');
  foreach ($lesfilms->film as $film) {
    echo "Titre :". utf8_decode($film->titre)."<br/>\n";
    foreach($film->attributes() as $a => $b) {
      echo $a, '="', $b, "\"\n";
    }
    print "Annee : {$film->annee} <br/>\n";
    }

Exécution :

Lecture XML avec SimpleXML

Resultat brut :

PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :Pandora and the flying Dutchman                   <br/>
idreal="7"
Annee :  <br/>
PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :Johnny Guitar                                     <br/>
idreal="8"
Annee :  <br/>
PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :Woman under the Influence (A)                     <br/>
idreal="9"
Annee :  <br/>
PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :Apartment (The)                                   <br/>
idreal="10"
Annee :  <br/>
PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :Victor/Victoria                                   <br/>
idreal="11"
Annee :  <br/>
PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :Modern Times                                      <br/>
idreal="12"
Annee :  <br/>
PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :Mépris (Le)                                       <br/>
idreal="13"
Annee :  <br/>
PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :Jour de fête                                      <br/>
idreal="14"
Annee :  <br/>
PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :Olvidados (Los)                                   <br/>
idreal="15"
Annee :  <br/>
PHP Deprecated:  Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5

Deprecated: Function utf8_decode() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/xml/SimpleXMLFilms.php on line 5
Titre :West Side Story                                   <br/>
idreal="16"
Annee :  <br/>

Manipuler JSON en PHP