Utilisation des fonctions DOM de PHP 5 pour créer des fichiers XML à partir de données SQL

Public visé


PHP et XML

Ce tutorial est destiné aux développeurs qui souhaitent extraire desdonnées d'une base de données et les insérer dans des fichiers XML afinqu'elles puissent être traitées, généralement en les transformant enHTML à l'aide d'un fichier XSL.

Cette méthode sépare complètement la couche de présentation(c'est-à-dire la génération de documents HTML) de la couche métier(l'application de règles d'entreprise en utilisant un langage commePHP) et que chaque une de ces couches peut être modifiée sans affecterl'autre.

Dans les exemples ci-dessous les données sont extraites de la base dedonnées dans un tableau associatif (une série de paires "nom =valeur"), et chaque élément du tableau est extrait et transféré dans lefichier XML. Le contenu du tableau associatif est par conséquent régientièrement par l'instruction SQL  « select ».

Dans les exemples ci-dessous, je vais montrer comment traiter lesdonnées issues d'une table unique, puis les données de deux tables avecune relation un-à-plusieurs. Enfin, je vais montrer comment insérer desdonnées supplémentaires sous la forme d'attributs XML.

Tout le code décrit dans le présent document peut être téléchargeable dans exemple d'application.

Conditions préalables

L'exemple de code requiert que vous avez l'extension DOM disponible dans votre installation de PHP. 

On suppose également que vous savez ce qu'un fichier XML, si ce n’estpas le cas vous pouvez voir nos tutoriaux sur le langage XML .

Une bonne connaissance de php et MySQL est aussi nécessaire .

Occurrences multiples d'une seule table

Le code suivant va prendre le contenu du $resultat_BDD (n'importe quel nombre de lignes, dont chacun contient une série de paires ( nom = valeur) et l'écrire dans une variable comme une chaîne XML. Cela peut par la suite être écrit dans un fichier disque ou transformé en un document HTML en utilisant les fonctions XSL qui sont intégrées à PHP. Pour plus d'informations sur l'utilisation de cette extension, veuillez vous référer aux fonctions XSL avec PHP 5 pour effectuer des Transformations XSL

Simplement, cette première partie du code se connecte à la base de données et exécute une requête :

Sélectionner le code
	  
<?php
if(!$dbconnect = mysql_connect('localhost', 'user', 'pass')) {
  echo "La connexion au serveur 'localhost' a échoé.";
   exit;
} 
if (!mysql_select_db('test')) {
  echo "Impossible de se connecter à la base de donnée 'test'";
   exit;
} 
$table_id = 'nom_table';
$query = "SELECT * FROM $table_id";
$resultat_BDD = mysql_query($query, $dbconnect);

 

Maintenant que nous avons nos données nous pouvons les transférer vers un document XML. Nous commençons par créer un nouveau document DOM. La commande suivante va définir le numéro de version XML à « 1.0 » et retourner la référence d'objet pour le nouveau document :

// créer un nouveau document XML
$document = new DomDocument('1.0');

Le premier élément que nous créons dans le document XML est connu comme élément racine. Chaque document XML doit avoir 1 et 1 seul, élément racine. 

Dans cet exemple je vais l’appelé « racine », mais vous pouvez utiliser n'importe quel nom que vous aimez.

Notez que vous devez créer l'élément et l'insérer dans le document avec deux fonctions.

// Créer le nœud racine
$racine = $document->createElement('racine');
$racine = $document->appendChild($racine);

Maintenant, nous sommes prêts pour commencer à ajouter les données que nous avons Récupérée de la base de données. 

Notez que je retourne chaque ligne dans un tableau associatif qui mefournit une liste de paires "nom = valeur". Cela rend tous lestraitements beaucoup plus faciles.

// Traiter une ligne à la fois en utilisant une boucle while
while($ligne = mysql_fetch_assoc($resultat_BDD)) {

La première tâche que je dois effectuer pour chaque ligne est d'ajouterun nouvel élément au document XML. Ici, j'ai créer un nouvel élément àl'aide du nom de la table, puis j'ai insérer dans le document comme unenfant de l'élément racine.

  // Ajouter un nœud pour chaque ligne
$element = $document->createElement($table_id);
$element = $racine->appendChild($element);

Maintenant, je vais effectuer une boucle sur chaque colonne de la ligneactuelle et insérer le nom de champ et la valeur correspondante. Vousverrez comme un tableau associatif rend la vie facile, je ne suisconcerné  moi-même ni par le nombre de colonnes qui ont été renvoyé parla requête de la base de données, ni avec l'ordre dans lequel ellessont présentées, ni comment chaque colonne du tableau est écrite.

  // Ajouter un nœud enfant pour chaque champ
  foreach ($ligne as $nomChamp => $valeurChamp) {

Notez qu'ici j'ai créer un nouvel élément pour le champ et puisl'insérer en tant qu'enfant de la ligne de base de données actuelle,telle qu'identifiée dans $element.

    $enfant = $document->createElement($nomChamp);
    $enfant = $element->appendChild($enfant);

Maintenant je dois ajouter la valeur du champ comme un nœud de texte,puis insérer comme un élément enfant du nœud actuel du champ, telqu'identifié dans $enfant.

    $valeur = $document->createTextNode($valeurChamp);
    $valeur = $enfant->appendChild($valeur);

Ces boucles ne sont pas terminés tant qu'ils n’ont pas traité chaquecolonne de chaque ligne qui a été Récupérée de la base de données.

  } // fin foreach
} // fin while

La fonction suivante retourne le document XML rempli sous forme dechaîne.

// Retourner le document xml rempli
$xml_chaine = $document->saveXML();

Ici, je vais tout simplement afficher les résultats au navigateur duclient, mais je pourrais tout aussi bien effectuer un traitementsupplémentaire tel que  passer à un processeur XSLT pour une transformation dans un autredocument, tel qu'un document HTML, en utilisant le contenu d'un fichierXSL séparé.

echo $xml_chaine;

?>

Le contenu du fichier XML produit avec ce code ressemblera à quelquechose comme suit :

Commençant par la déclaration XML, avec le numéro de version etimmédiatement suivi par le nœud racine.

<?xml version="1.0"?>
<racine>

Pour chaque ligne de base de données il sera établit un élément, comme enfant du nœud racine, qui contient le nom de la table chaque élémentligne dispose d'un élément enfant séparée pour chaque colonne danscette ligne. 

Notez que chaque élément de colonne contient un nœud de texte pour savaleur, tandis que l'élément  ligne n'a pas de nœud de texte.

Ceci sera répété pour chaque colonne dans chaque ligne. Après ladernière colonne, remarquez la balise de fermeture pour l'élémentactuel de la ligne, après quoi le groupe de lignes/colonnes doit êtrerépété pour chaque ligne supplémentaire qui a été extraite de la basede données et transférée vers le fichier XML.

  
<ligne1>
   <colonne1>valeur1</colonne1>
   <colonne2>valeur2</colonne2>
   ............
   <colonneX>valeurX</colonneX>
 </ ligne 1>
 < ligne 2>
   ............
 </ ligne 2>

La dernière ligne dans un fichier XML sert à fermer le nœud racine.

</racine>

Notez que chaque élément dans le document XML a une balise d’ouvertureet une balise de fermeture dans leformat <element>...</element>. Ceci identifie le nom dunœud dans l'arborescence du document. 

Ce qui est entre ces deux balises est un nœud enfant de cet élément. Cenœud enfant peut être un nœud de texte ou un autre élément.

Vous verrez parfois un élément dans un document XML indiquécomme <element />. Cela signifie que l'élément est vide.  XMLpermet de fusionner l'ouverture et la fermeture des balises dans uneseule balise, lorsqu'un élément est vide.

La relation parent enfant

Dans l'exemple suivant, le code XML contient les données de deux tablesdisposées dans une relation  parent enfant ou externe interne, vu queles éléments de l’une de ces tables seront enfants des éléments del’autre table. 

Dans le code de la requête suivante deux résultats sont produites: $externeResultat pour la table parente et $interneResultat pour latable enfant.

 Je ne commenterai le code que lorsqu'il y a des différences avec ce que nous avons vu ci haut.

<?php
if(!$dbconnect = mysql_connect('localhost', 'user', 'pass')) {
   echo "La connexion au serveur 'localhost' a échoé.";
   exit;
}
if (!mysql_select_db('test')) {
   echo "Impossible de se connecter à la base de donnée 'test'";
   exit;
}

Voici par exemple, les requêtes de base de données distincte pourchacune des deux tables :

 ici parent_table est le nom de la table dont on veut qu’elle soit parent

$exterene_table = 'parent_table';
$query = "SELECT * FROM $exterene_table WHERE colonne='valeur'";
$externeResultat = mysql_query($query, $dbconnect);

ici child_table est le nom de la table dont on veut qu’elle soit enfant

$interne_table = 'child_table';
$query = "SELECT * FROM $interne_table WHERE colonne='valeur'";
$interneResultat = mysql_query($query, $dbconnect);

Ici, nous créons un nouveau document DOM :

$document = new DomDocument('1.0');

et ajoutez le nœud racine :

$racine = $document->createElement('racine');
$racine = $document->appendChild($racine);

Ici, nous ajoutons un nœud pour la ligne unique provenant de la tableparente :

$exterene = $document->createElement($exterene_table);
$exterene = $racine->appendChild($exterene);

N'oublions pas d'ajouter chaque valeur de la colonne comme un élémentenfant pour le nœud $exterene .

$ligne = mysql_fetch_assoc($externeResultat);

 Ajouter un nœud enfant pour chaque champ parent en utilisant foreach

foreach ($ligne as $nomChamp => $valeurChamp) {
    $enfant = $document->createElement($nomChamp);
    $enfant = $exterene->appendChild($enfant);
    $valeur = $document->createTextNode($valeurChamp);
    $valeur = $enfant->appendChild($valeur);
}

Ici, nous ajoutons un nœud pour chaque ligne provenant de la tableenfant. 

Notez que chacune de ces lignes est inséré comme un nœud enfant du nœudde $exterene , pas le nœud $racine .Chaque nœud $interne aura sesvaleurs de la colonne insérées comme ses enfants.

 traiter toutes les lignes de la table interne en utilisant la bouclewhile et la boucle foreach ci-dessus.

while ($ligne = mysql_fetch_assoc($interneResultat)) {
    // Ajouter le nœud pour chaque enregistrement
    $interne = $document->createElement($interne_table);
    $interne = $exterene->appendChild($interne);
    // Ajouter un nœud enfant pour chaque champ
    foreach ($ligne as $nomChamp => $valeurChamp) {
        $enfant = $document->createElement($nomChamp);
        $enfant = $interne->appendChild($enfant);
        $valeur = $document->createTextNode($valeurChamp);
        $valeur = $enfant->appendChild($valeur);
    }
}

Enfin, téléchargez le document XML rempli et l'envoyer au navigateur duclient.

// Téléchargez le document xml rempli
$xml_string = $document->saveXML();
echo $xml_string;
?>

Le code ci-dessus va produire un fichier XML avec la structure suivante:

<?xml version="1.0"?>
<racine>
  <parent_table>
    <colonne1>valeur1</colonne1>
    <colonne2>valeur2</colonne2>
    ............
    <colonneX>valeurX</colonneX>
    <child_table>
      <colonne1>valeur1</colonne1>
      <colonne2>valeur2</colonne2>
      ............
      <colonneX>valeurX</colonneX>
    </child_table>
    <child_table>
      ............
    </child_table>
  </parent_table>
</racine>

C'est lastructure <racine> à <parent_table> à <child_table>. Le <parent_table> ades nœuds enfants qui sont ses valeurs de colonnes ainsi que desoccurrences multiples de <child_table>.

Ajout d'attributs facultatifs

Il peut parfois être nécessaire d'inclure des informationssupplémentaires pour un élément avec les données XML, et cela peut êtrefait sous la forme d'attributs. 

Un attribut a un nom et une valeur,  un nombre quelconque d'attributspeut être ajouté à un élément. Cela doit être fait en utilisant laméthode  'setAttribute' immédiatement après la méthode  'appendChild'et avant toute autre méthode de '->createTextNode', comme illustré dans l'extrait de code suivant :

$enfant = $document->createElement($nomChamp);
$enfant = $exterene->appendChild($enfant);
$enfant->setAttribute('attr1', 'attrval1');
$enfant->setAttribute('attr2', 'attrval2');
$valeur = $document->createTextNode($valeurChamp);
$valeur = $enfant->appendChild($valeur);

Ces valeurs d'attribut apparaît alors au sein de la balise de début del'élément, comme suit :

<?xml version="1.0"?>
<racine>
  <some_table>
    <colonne1 attr1="attrval1"attr2="attrval2">valeur1</colonne1>
    <colonne2 attr1="attrval1"attr2="attrval2">valeur2</colonne2>
    <colonne3 attr1="attrval1"attr2="attrval2">valeur3</colonne3>
  </some_table>
</racine>

Notez que vous pouvez insérer des attributs pour les éléments de ligneainsi que les éléments de la colonne.

Utilisation des caractères multi-octets

Si vous souhaitez traiter les caractères avec accents (comme dans, à,è, í, ö et û) alors vous devez modifier le codage de caractères dudocument DOM en UTF-8. 

 Cela nécessite les modifications suivantes concernant les exemples decode :

(1) Pour définir le codage de caractères du document DOM, vous devezmodifier la ligne suivante :

  $xml_doc = new DomDocument('1.0', 'UTF-8');

(2) La conversion de jeu de caractères par défaut(voir default_charset dans le fichier php.ini) en UTF-8 en insérant uneseule ligne comme suit:

  
foreach ($ligne as $nomChamp => $valeurChamp) {
    $enfant = $document->createElement($nomChamp);
    $enfant = $interne->appendChild($enfant);
    $valeurChamp =mb_convert_encoding($valeurChamp,'UTF-8','ISO-8859-1');
    $valeur = $document->createTextNode($valeurChamp);
    $valeur = $enfant->appendChild($valeur);
  } // foreach

Remarque : Afin que cela fonctionne, vous devez activer les fonctions Chaîne multi-octets en PHP.

Par carabde 30 mars 2015