Flux rss

PHP - Parser du XML

 

Introduction à XML

PHP permet l'analyse syntaxique (parsage ou parsing en anglais) d'un document XML.
Le langage XML (eXtensible Markup Language, traduisez Langage à balises extensibles) est un métalangage, c'est-à-dire un langage permettant de définir votre propre langage. Ainsi contrairement au langage HTML, le langage XML permet d'aller définir vos propres balises, ce qui permet de séparer la présentation du document de son contenu.

Cette séparation entre le contenu et la présentation se fait à l'aide d'un analyseur syntaxique (parseur), c'est-à-dire un programme capable de vérifier la cohérence de la syntaxe du document et de l'interpréter afin de mettre en page son contenu. PHP propose une extension permettant de mettre au point facilement des analyseurs XML. Cette extension utilise la librairie expat disponible à http://www.jclark.com/xml/.

Installer l'extension XML

L'extension XML de PHP supporte la librairie expat disponible à http://www.jclark.com/xml/.
Sur les serveurs Apache récents (de version supérieure à la 1.3.7) la librairie expat est installée en standard. sur les serveurs apache de version antérieure à la 1.3.7 il suffit de télécharger cette librairie :

Pour activer le support de cette librairie lors de l'installation de PHP il suffit de lancer la configuration de PHP avec l'option --with-xml.

Pour vérifier que votre installation supporte bien la librairie expat, il vous suffit de créer un fichier phpinfo.php3 contenant uniquement les lignes suivantes

<?
phpinfo();

?>

Fonctionnement de l'extension XML

Les analyseurs XML sont également divisés selon l'approche qu'ils utilisent pour traiter le document. On distingue actuellement deux types d'approches :

  • Les API utilisant une approche hiérarchique : les analyseurs utilisant cette technique construisent une structure hiérarchique contenant des objets représentant les éléments du document, et dont les méthodes permettent d'acCèder aux propriétés. La principale API utilisant cette approche est DOM (Document Object Model)
  • Les API basés sur un mode événementiel permettent de réagir à des événements (comme le début d'un élément, la fin d'un élément) et de renvoyer le résultat à l'application utilisant cette API. SAX (Simple API for XML est la principale interface utilisant l'aspect événementiel Ainsi, on tend à associer l'approche hiérarchique avec DOM et l'approche événementielle avec SAX.

Considérons le document XML suivant :

<debut>

	Bienvenue sur CCM - http://www.commentcamarche.net
</debut>

Avec un parseur XML utilisant une approche événementielle, les 3 événements suivants seraient générés :

  • Start Element : debut
  • Start CDATA section, value : Bienvenue sur CCM - http://www.commentcamarche.net
  • Close Element : debut

L'extension XML fonctionne selon un mode événementiel, c'est-à-dire qu'elle définit des fonctions permettant de réagir aux divers événements :

  • La fonction xml_set_element_handler() permet d'associer une action au début, à la fin d'un élément ou bien au contenu d'un attribut
  • La fonction xml_set_character_data_handler() permet d'associer un événement au contenu textuel des balises
  • La fonction xml_set_processing_instruction_handler() permet d'associer une action à la rencontre d'une instruction de traitement
  • La fonction xml_set_notation_decl_handler() associe un traitement à la détection d'une instruction de traitement
  • La fonction xml_set_external_entity_ref() permet de détecter un appel à une entité externe

Création de l'analyseur XML

La première étape consiste à créer un analyseur XML (ou plus exactement pour utiliser une instance de parseur XML) grâce à la fonction xml_create_parser() $xml_parseur = xml_parser_create(); Une fois le parseur créé, il s'agit de lui associer des événements, c'est-à-dire qu'il s'agit de créer des fonctions qui seront appelées par le parseur en cas de déclenchement d'un événement.
L'extension XML (expat) définit 7 types d'événements et leurs gestionnaires (handlers) associés :

Evénement Gestionnaire associé Description
Elements xml_set_element_handler() ce gestionnaire gère les ouvertures et fermetures de balises
Character Data xml_set_character_data_handler() Ce handler permet d'associer une fonction aux données textuelles (hors des balises)
External Entities xml_set_external_entity_ref_handler() Ce gestionnaire intercepte les appels à des entités externes
Unparsed external entities xml_set_unparsed_entity_decl_handler() Affecte les gestionnaires d'entités non déclarées de l'analyseur XML
Processing instructions xml_set_processing_instruction_handler() Permet d'intercepter l'occurrence d'une instructrion de traitement (PI, processing instruction)
Notation declarations xml_set_notation_decl_handler() Gère les occurences de déclarations de notation
default xml_set_default_handler() Permet de gérer tous les événements pour lesquels aucun gestionnaire n'a été défini

Toutes ces fonctions de gestion des événements prennent comme premier argument l'instance du parseur qui a été renvoyée par la fonction xml_create_handler().

Prenons l'exemple de la fonction xml_set_element_handler(). Cette fonction nécessite trois arguments :

  • L'instance du parseur
  • Le nom de la fonction qui gère les balises ouvrantes
  • Le nom de la fonction qui gère les balises fermantes
Les fonctions de gestion des événements définies par l'utilisateur doivent exister avant de commencer à parser le document. De plus leurs définitions doivent concorder exactement avec le prototype défini dans le manuel PHP (http://www.php.net).

Par exemple la fonction chargée de gérer l'événement "balise ouvrante" doit comporter trois paramètres :

function ouverture ($parser, $name, $attrs){
 echo "$name<BR>";

}
Son nom et le nom de ses attributs peuvent être modifiés mais le nombre de ses arguments et leur ordre doit être conforme au manuel PHP. Dans le cas de la fonction associée à l'ouverture de balise, le premier argument est l'identifiant de l'instance du parseur, le second est le nom de la balise rencontrée (pour une balise <Debut> sa valeur sera "Debut") et le troisième est un tableau associatif contenant tous les noms des attributs de cet élément et leur valeur.

Voici certains gestionnaires d'événement que nous allons définir

  • la fermeture d'une balise XML :
    function fermeture ($parser, $name){
     echo "$name<BR>";
    
    }

    Le prototype est le même que pour le gestionnaire d'événement associé aux balises ouvrantes
  • du texte est trouvé hors des balises :
    function texte ($parser, $data_text){
     return $data_text;
    
    }

    Dans cette fonction le deuxième argument est le texte retourné par le gestionnaire d'événement

  • une fonction par défaut :
    function defaut (){
     return TRUE;
    
    }
Il suffit ensuite d'utiliser les fonctions XML fournies par PHP (appelés gestionnaires d'événement ou en anglais event handler) pour associer les fonctions que vous avez définies à des événements XML :
  • La fonction xml_set_element_handler() permet de définir les fonctions associées à l'ouverture et à la fermeture d'une balise XML (dans notre cas il s'agit des fonctions ouverture() et fermeture()) :
    xml_set_element_handler($xml_parseur, "ouverture", "fermeture");
  • La fonction xml_set_character_data_handler() définit la fonction associée à la rencontre de texte en dehors ou entre les balises XML :
    xml_set_character_data_handler($xml_parseur, "texte");
  • La fonction xml_set_default_handler() permet d'associer une fonction par défaut aux événements non traités
    xml_set_default_handler($xml_parseur,"defaut");

La fonction xml_parser_set_option() permet de définir des options de parsage. Le premier argument est bien évidemment l'instance du parseur. Le second argument peut prendre deux valeurs (0 ou 1, représenté par la constante XML_OPTION_CASE_FOLDING) : cette option est activée par défaut. Le fait de désactiver cette option force le gestionnaire d'événement à transformer les noms des balises en majuscule (il est essentiel de ne pas la désactiver car le XML est sensible à la casse, c'est-à-dire qu'il différencie minuscules et majuscules). Le troisième argument définit quel encodage utiliser dans le parseur XML (ISO-8859-1, US-ASCII ou UTF-8). Par défaut l'encodage est celui de xml_parser_create())

xml_parser_set_option($xml_parseur, XML_OPTION_CASE_FOLDING);

Pour parser un fichier XML, il suffit de l'ouvrir en lecture, puis de faire appel à la fonction xml_parse() :

$fp = fopen("essai.xml", "r") or die("
Fichier introuvable. L'analyse a ete suspendue"); while ($fdata = fread($fp, 2048)){ xml_parse($xml_parseur, $fdata, feof($fp)) or die( sprintf("Erreur XML : %s à la ligne %d\n", xml_error_string(xml_get_error_code($xml_parseur)), xml_get_current_line_number($xml_parseur)) ); }

Si le document XML n'est pas bien formé la fonction xml_parse() renvoie la valeur false

Les fonctions xml_error_string() et xml_get_current_line_number() permettent, en cas d'erreur, d'afficher l'erreur qui a été générée ainsi que le numéro de la ligne du fichier XML où elle se trouve !

Appel à des entités externes

Comme chacun devrait le savoir, il est possible avec XML de faire appel à des entités externes, c'est-à-dire importer des éléments XML stockés dans un autre fichier. Ainsi il est essentiel lors du parsage d'un fichier XML d'incorporer le document externe au document XML principal.
Cela est possible grâce au gestionnaire d'entité externe permettant d'appeler une fonction à chaque fois qu'une balise du type suivant est rencontrée dans le document XML :

<!ENTITY systemEntity SYSTEM "externe.xml">
<?
// Fichier à analyser
$file = "data.xml";

// variable de la profondeur du parcours de l'arbre
$depth = array();

// Etat de la pile de parcours du document XML
$stack = array();

// Valeur d'un dernier élément lu
$globaldata ="";

// Fonction associée à l’événement début d’élément
function startElement($parser, $name, $attrs)
{

global $depth;

global $stack;

for ($i = 0; $i < $depth[$parser]; $i++)
{print " ";}
array_push($stack,$name);

$depth[$parser]++;

print "Début de l'élément : ".$name."\n -- ";

print "profondeur : ".$depth[$parser]." -- Attributs de l'élément : ";

//affichage des attributs de l'élément
while (list ($key, $val) = each ($attrs))
{echo "$key => $val";}
print " ";

}

// Fonction associée à l’événement fin d’élément
function endElement($parser, $name)
{

global $depth;

global $stack;

global $globaldata;

for ($i = 0; $i < $depth[$parser]-1; $i++)
{print " ";}
print "Fin de l'élément : ".$name." avec la valeur :".$globaldata." -- ";

print "profondeur : ".$depth[$parser]." ";

$depth[$parser]--;

array_pop($stack);

}

// Fonction associée à l’événement données textuelles
function characterData($parser, $data)
{

global $globaldata;

$globaldata = $data;

}

// Fonction associée à l’événement de détection d'un appel d'entité externe
function externalEntityRefHandler($parser,
								  $openEntityNames,
								  $base,
								  $systemId,
								  $publicId)
{

if ($systemId)
{ if (!list($parser, $fp) = new_xml_parser($systemId))
{

printf("Impossible d'ouvrir %s à %s\n",
				   $openEntityNames,
				   $systemId);
return FALSE;

}

while ($data = fread($fp, 4096))
{

if (!xml_parse($parser, $data, feof($fp)))
{

printf("Erreur XML : %s à la ligne %d lors du traitement de l'entité %s\n",
			   xml_error_string(xml_get_error_code($parser)),
			   xml_get_current_line_number($parser),
			   $openEntityNames);

xml_parser_free($parser);

return FALSE;

}

}

xml_parser_free($parser);

return TRUE; } return FALSE;

}

// Fonction de création du parser et d'affectation
// des fonctions aux gestionnaires d'événements
function new_xml_parser($file)
{

global $parser_file;

//création du parseur
$xml_parser = xml_parser_create();

//Activation du respect de la casse du nom des éléments XML
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 1);

//Déclaration des fonctions à rattacher au gestionnaire d'événement
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
xml_set_external_entity_ref_handler($xml_parser, "externalEntityRefHandler");

//Ouverture du fichier
if (!($fp = @fopen($file, "r"))) { return FALSE; }
//Transformation du parseur en un tableau
if (!is_array($parser_file))
{ settype($parser_file, "array"); }
$parser_file[$xml_parser] = $file;

return array($xml_parser, $fp);

}

// Appel à la fonction de création et d'initialisation du parseur
if (!(list($xml_parser, $fp) = new_xml_parser($file)))
{ die("Impossible d'ouvrir le document XML"); }
// Traitement de la ressource XML
while ($data = fread($fp, 4096))
{

if (!xml_parse($xml_parser, $data, feof($fp)))
   { die(sprintf("Erreur XML : %s à la ligne %d\n",
			  xml_error_string(xml_get_error_code($xml_parser)),
			  xml_get_current_line_number($xml_parser)));
   }
}

// Libération de la ressource associée au parser
xml_parser_free($xml_parser);

?>

Article écrit par Jean-François Pillou

Ce document intitulé « PHP - Parser du XML » issu de Comment Ça Marche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Ajouter adresse ip (Résolu)Bonjour Je voudrais ajouter une 2eme adresse ip a la meme interface reseau, donc une interface avec 2 adresses ip ,et une seule gateway Et est ce qu'il ya un moyen de definir aussi la metrique de l'interface Merci ;-) java,c++,php,xml,... www.commentcamarche.net/forum/affich-2577585-ajouter-adresse-ip
[BDD Ingres]export de donness (Résolu)Bonjour J'utilise le Sgbd INGRES,et je voudrais savoir si ya un moyen d'exporter une Requete vers en fichier texte avec un ";" comme separateur entre les colonnes, du style de BCP sous MS SQL Server Merci java,c++,php,xml, xforms,mysql www.commentcamarche.net/forum/affich-2650092-bdd-ingres-export-de-donness
[PHP/XML] DomDocument::getElementsByTagName (Résolu)Bonjour, J'ai besoin de recuperer du XML dans une page PHP puis d'en extraire un tag seulement. J'utilise donc DomDocument qui est tres performant, et la fonction DomDocument::getElementsByTagName. Seulement voila si je charge mon XML... www.commentcamarche.net/forum/affich-8541504-php-xml-domdocument-getelementsbytagname
[PHP] Upload de fichiersLe langage PHP permet de gérer des fichiers envoyés (uploadés) grâce à un formulaire HTML. Formulaire d'envoi de fichiers Configuration de PHP pour permettre l'upload Récupération du fichier avec PHP Formulaire d'envoi de fichiers La... www.commentcamarche.net/faq/sujet-889-php-upload-de-fichiers
[PHP] Notice: Undefined index:Si vous utilisez les tableaux $_POST ou $_GET pour récupérer les variables de vos formulaires ou autres, il se peut que vous tombiez sur cette erreur: Notice: Undefined index 'champs du tableau' in 'chemin du fichier php en cours d'execution' on line... www.commentcamarche.net/faq/sujet-1391-php-notice-undefined-index
[PHP] Parse error, unexpected T_STRING, expecting ',' or ';'Cette erreur, fréquente, se produit notamment lorsqu'un guillemet est présent dans une chaîne délimitée par ce même type de guillemets, par exemple : www.commentcamarche.net/faq/sujet-869-php-parse-error-unexpected-t-string-expecting-or
[PHP & XML] multiplication par 0,4 (Résolu)Bonjour, Lorsque je parse un document XML avec simpleXML et qu'ensuite je traite les données je me retrouve avec des résultats "tronqués"! Je m'explique, voila le code : foreach ($xml->produit as $produit) { echo $produit->quantite*$produit... www.commentcamarche.net/forum/affich-3273136-php-xml-multiplication-par-0-4
PHP et XML (Résolu)Bonjour j'aimerai bien savoir SVP est ce qu'on a la possibilté d'inclure un code PHP au sein d'une page XML . Merçi en avance aux gens qui veulent m'aider. www.commentcamarche.net/forum/affich-1923554-php-et-xml
Xml en tableau php (Résolu)Bonjour tout le monde, j'aimerais conventir un fichier xml en tableau php, j'utilise php 4 et domxml si jamais j'aimerais printer mes infos comme cela : $a = array ('a' => 'pomme', 'b' =>... www.commentcamarche.net/forum/affich-4109153-xml-en-tableau-php
Télécharger Notepad++Notepad++ est un editeur de code source qui supporte plusieurs langages. Il s'agit d'un logiciel libre performant et compact. Fonctionnalités de Notepad++ Coloration syntaxique pour les langages suivants : C, C++, Java, C#, XML, HTML, PHP,... www.commentcamarche.net/telecharger/telecharger-34055333-notepad
Télécharger Notepad2Notepad2 est un blc-note libre possédant des fonctionnalités avancées de coloration syntaxique. Fonctionnalités Coloration syntaxique pour les langages suivants : HTML, XML, PHP, ASP (JScript, VBS), CSS, JavaScript, VBScript, C/C++, C#,... www.commentcamarche.net/telecharger/telecharger-34055332-notepad2
Télécharger DriveImage XMLDriveImage XML est un programme permettant de faire des images du système (partitions et lecteurs logiques) à des fins de sauvegarde, à la manière de Norton Ghost. Ce programme permet : De créer des images des lecteurs logiques et des... www.commentcamarche.net/telecharger/telecharger-34055109-driveimage-xml
XML - Introduction XML (entendez eXtensible Markup Language et traduisez Langage à balises étendu, ou Langage à balises extensible) est en quelque sorte un langage HTML amélioré permettant de définir de nouvelles balises. Il s'agit effectivement d'un langage permettant... www.commentcamarche.net/xml/xmlintro.php3
PHP - Introduction PHP est un langage interprété (un langage de script) exécuté du côté serveur (comme les scripts CGI, ASP, ...) et non du côté client (un script écrit en Javascript ou une applet Java s'exécute sur votre ordinateur...). La syntaxe du langage provient... www.commentcamarche.net/php/phpintro.php3
PHP - Les fichiers Avec PHP, la création ou la lecture de fichiers est, une fois de plus, assez simple. Il existe une multitude de fonctions dédiées à l'utilisation des fichiers. La communication entre le script PHP et le fichier est repérée par une variable, indiquant... www.commentcamarche.net/php/phpfich.php3
Toutes les réponses pour « PHP XML »