PHP Technologies XML DESS NAPI - Filière 2 - Module D3 Antoine WIDLÖCHER Université de Caen
Plan de l exposé Introduction événementielle Utilisation d A. WIDLÖCHER 25 février 2004 diapo 1 sur 39
Plan de l exposé Introduction événementielle Utilisation d A. WIDLÖCHER 25 février 2004 diapo 1 sur 39
Contexte utilisation de plus en plus fréquente des techno. XML en particulier sur le web XML, XSL,, XSL-FO, RDF, RSS, SVG... à différentes fins : stockage de données structurées : XML en général transformation, restructuration des données :... web sémantique : RDF... syndication, partage : RDF, RSS... export : XSL,, XSL-FO... A. WIDLÖCHER 25 février 2004 diapo 1 sur 39
Exemples d utilisation web configuration d un site plan du site en XML génération automatique d une barre de menus génération automatique d une page «plan» paramètres divers auxquels on pourra souhaiter accéder différemment «base de données», stockage d information ne pas assimiler aux bases de données XML séparation contenu brut / mise en forme capter la structure logique d un site alternative à l utilisation d une BD relationnelle A. WIDLÖCHER 25 février 2004 diapo 2 sur 39
Exemples d utilisation web automatiser la publication de contenu dans l esprit de Cocoon par exemple créer des chaînes de traitement de l information transitions entre médias web : HTML, RDF... papier : FO, PDF... partage d informations, syndication rendre des news accessibles «de l extérieur» considérer un site comme une source d information proposer un service web A. WIDLÖCHER 25 février 2004 diapo 3 sur 39
Avantages interopérabilité XML constitue un bon format d échange l information est accessible depuis d autres outils normalisation et respect des standards... portabilité les données acquièrent une relative indépendance par rapport au langage utilisé par rapport au traitement qui en est fait «maniabilité» déplacement de l application et des données sauvegarde de l application et des données plus simple qu un dump de BD relationnelle A. WIDLÖCHER 25 février 2004 diapo 4 sur 39
Technologies envisagées dans le cadre de cette introduction, nous envisagerons : lecture événementielle dans l esprit de SAX modèle de représentation objet du document transformations d arbres XML notons qu il existe également SimpleXML en PHP accès simplifié aux documents XML non abordé ici A. WIDLÖCHER 25 février 2004 diapo 5 sur 39
Exemple d étude but : créer dynamiquement une barre de navigation on dispose du fichier XML suivant : 1 <?xml version="1.0" encoding="iso 8859 1"?> 2 <menu> 3 <rubrique> 4 <label lang="fr ">Accueil</label> 5 <url>accueil.php</url> 6 </rubrique> 7 8 <rubrique> 9 <label lang="fr ">Curriculum Vitae</label> 10 <url>cv.php</url> 11 </rubrique> 12 13 <rubrique> 14 <label lang="fr ">Réalisations</label> 15 <url> realisations.php</url> 16 </rubrique> 17 18 <rubrique> 19 <label lang="fr ">Liens</label> 20 <url>liens.php</url> 21 </rubrique> 22 </menu> A. WIDLÖCHER 25 février 2004 diapo 6 sur 39
Plan de l exposé Introduction événementielle Principes Méthode d analyse Utilisation d A. WIDLÖCHER 25 février 2004 diapo 7 sur 39
Plan de l exposé Introduction événementielle Principes Méthode d analyse Utilisation d A. WIDLÖCHER 25 février 2004 diapo 7 sur 39
Principes on utilise la librairie expat utilisée par PHP 4 remplacée par libxml2 dans PHP 5 mais interface en principe conservée le principe de fonctionnement de l analyseur : lecture linéaire, séquentielle du XML en fonction des éléments rencontrés (événements)...... on déclenche certaines opérations on associe des gestionnaires d événements aux événements possibles A. WIDLÖCHER 25 février 2004 diapo 7 sur 39
Avantages / Inconvénients Avantages solution économique en mémoire lecture en une seule passe sans nécessité d attendre la fin de la lecture Inconvénients pas de représentation en mémoire du document un nœud ne peut pas être revisité pas de validation au sens XML A. WIDLÖCHER 25 février 2004 diapo 8 sur 39
Événements on va définir des opérations en fonction des événements rencontrés, dont principalement : début / fin du document on pourra initialiser nos structures de données début / fin d un élément on pourra récupérer le contenu de l élément on pourra le mettre en relation avec son nœud père on pourra récupérer les différents attributs rencontre d un nœud de type texte on pourra récupérer le contenu textuel de l élément A. WIDLÖCHER 25 février 2004 diapo 9 sur 39
Plan de l exposé Introduction événementielle Principes Méthode d analyse Utilisation d A. WIDLÖCHER 25 février 2004 diapo 10 sur 39
Créa o / Dest o du parseur on commence l analyse par la création d un parseur en utilisant xml_parser_create() on la termine par la destruction de celui-ci : en utilisant xml_parser_free() 1 <?php 2 3 $parser=xml_parser_create(); 4 5 / 6 définition des gestionnaires d événements 7 analyse 8 / 9 10 xml_parser_free($parser); 11 12?> A. WIDLÖCHER 25 février 2004 diapo 10 sur 39
Gestion des événements on spécifie les fonctions à appeler lors de la rencontre des différents événements on les désigne par leur nom! (principe de callback) on utilise xml_set_element_handler() on utilise xml_set_character_data_handler() 1 <?php 2 $parser=xml_parser_create(); 3 4 xml_set_element_handler($parser, "debutelement", "finelement"); 5 xml_set_character_data_handler($parser, "cdata"); 6 7 / 8 définition des méthodes ainsi appelées (debutelement,finelement,cdata) 9 analyse 10 / 11 12 xml_parser_free($parser); 13?> A. WIDLÖCHER 25 février 2004 diapo 11 sur 39
Gestion des événements on définit les fonctions ainsi appelées on utilise les noms définis ci-dessus leurs signatures sont prédéfinies c est par ce biais qu on définit l analyse voulue 1 <?php 2 $parser=xml_parser_create(); 3 4 xml_set_element_handler($parser, "debutelement", "finelement"); 5 xml_set_character_data_handler($parser, "cdata"); 6 7 xml_parser_free($parser); 8 9 function debutelement($parser, $name, $attrs) { 10 } 11 12 function finelement($parser, $name) { 13 } 14 15 function cdata($parser,$cdata){ 16 } 17?> A. WIDLÖCHER 25 février 2004 diapo 12 sur 39
Récupération des paramètres selon le handler considéré, on récupère nom d élément (string) attributs (tableau associatif) CDATA (string) casse pour les noms d éléments et d attributs (clefs de tableau) on récupère uniquement des majuscules propriété modifiable par xml_parser_set_option() A. WIDLÖCHER 25 février 2004 diapo 13 sur 39
Récupération des paramètres encoding en interne, PHP utilise UTF-8 mais source et destination sont par défaut en iso-8859-1 source : au moment de la création du parser (xml_parser_create()), on peut spécifier un encodage source (iso-8859-1 par défaut) non modifiable par la suite destination : par défaut, l encodage destination est le même que l encodage source, mais on peut le modifier avec xml_parser_set_option() appliqué à XML_OPTION_TARGET_ENCODING modifiable A. WIDLÖCHER 25 février 2004 diapo 14 sur 39
Récupération des paramètres 1 <?php 2 $parser=xml_parser_create("iso 8859 1"); 3 4 xml_set_element_handler($parser, "debutelement", "finelement"); 5 xml_set_character_data_handler($parser, "cdata"); 6 7 xml_parser_set_option($parser,xml_option_target_encoding,"utf 8"); 8 9 / 10 lancement de l analyse 11 / 12 13 xml_parser_free($parser); 14 15 function debutelement($parser, $name, $attrs) { 16 print $name; 17 print_r ( $attrs ) ; 18 } 19 20 function finelement($parser, $name) { } 21 22 function cdata($parser,$cdata){ 23 print $cdata; 24 } 25?> A. WIDLÖCHER 25 février 2004 diapo 15 sur 39
Lancement de l analyse reste à récupérer les données XML et à lancer l analyse 1 <?php 2 $parser=xml_parser_create(); 3 4 xml_set_element_handler($parser, "debutelement", "finelement"); 5 xml_set_character_data_handler($parser, "cdata"); 6 7 $file ="menu.xml"; 8 $fp = fopen( $file, "r") ; 9 $data = fread($fp, filesize ( $file )) ; 10 11 xml_parse($parser, $data); 12 13 xml_parser_free($parser); 14 15 function debutelement($parser, $name, $attrs) { } 16 17 function finelement($parser, $name) { } 18 19 function cdata($parser,$cdata){ } 20?> A. WIDLÖCHER 25 février 2004 diapo 16 sur 39
Gestion des erreurs nous pouvons améliorer le contrôle des erreurs 1 <?php 2 $parser=xml_parser_create(); 3 4 xml_set_element_handler($parser, "debutelement", "finelement"); 5 xml_set_character_data_handler($parser, "cdata"); 6 7 $file ="menu.xml"; 8 if (!( $fp = fopen( $file, "r"))){die("impossible d ouvrir le fichier XML");} 9 $data = fread($fp, filesize ( $file )) ; 10 11 if (! xml_parse($parser, $data)) { 12 die( sprintf ("erreur XML : %s à la ligne %d", 13 xml_error_string(xml_get_error_code($parser)), 14 xml_get_current_line_number($parser))); 15 } 16 17 xml_parser_free($parser); 18 19 function debutelement($parser, $name, $attrs) { } 20 21 function finelement($parser, $name) { } 22 23 function cdata($parser,$cdata){ } 24?> A. WIDLÖCHER 25 février 2004 diapo 17 sur 39
Lecture progressive pour éviter d attendre la lecture complète du XML on peut lire en plusieurs fois préciser une condition d arrêt à xml_parse() 1 <?php 2 $parser=xml_parser_create(); 3 xml_set_element_handler($parser, "debutelement", "finelement"); 4 xml_set_character_data_handler($parser, "cdata"); 5 6 if (!( $fp = fopen("menu.xml", "r"))) { die("impossible d ouvrir le fichier XML"); } 7 while ($data = fread($fp, 4096)) { 8 if (! xml_parse($parser, $data, feof($fp))) { 9 die( sprintf ("erreur XML : %s à la ligne %d", 10 xml_error_string(xml_get_error_code($parser)), 11 xml_get_current_line_number($parser))); 12 } 13 } 14 xml_parser_free($parser); 15 16 function debutelement($parser, $name, $attrs) { } 17 function finelement($parser, $name) { } 18 function cdata($parser,$cdata){ } 19?> A. WIDLÖCHER 25 février 2004 diapo 18 sur 39
Méthode d analyse en général, on utilise des piles pour mémoriser la structure de l arbre pour déterminer les liens de parenté en PHP pas de structure de type pile la structure de données fondamentale est le tableau différentes méthodes permettent d utiliser un tableau en tant que pile : array_push() : permet d empiler des éléments array_pop() : permet de récupérer le dessus de la pile rappel : ces fonctions ne sont pas des méthodes d objets! A. WIDLÖCHER 25 février 2004 diapo 19 sur 39
POO dans une perspective objet nous sommes confrontés à un problème de définition de callback l analyseur utilise les noms des fonctions à appeler or au sein d une classe le nom ne suffit pas à désigner une méthode Solution 1 : lors de l affectation des handlers avec xml_set_character_data_handler() et xml_set_element_handler() à la place des noms de fonctions passés en paramètres on peut passer un tableau contenant une référence à l objet dont on souhaite appeler une méthode (&$this) le nom de la méthode d objet à appeler A. WIDLÖCHER 25 février 2004 diapo 20 sur 39
POO (suite) Solution 2 : pour l ensemble de l analyseur on utilise la fonction xml_set_object() pour mettre en relation un parseur et un objet 1 <?php 2 class Menu{ 3 var $xml_parser; 4 5 function Menu($file){ 6 $this >xml_parser = xml_parser_create(); 7 xml_set_object($this >xml_parser, &$this); 8 xml_set_element_handler($this >xml_parser, "debutelement", "finelement"); 9 xml_set_character_data_handler($this >xml_parser, "cdata"); 10 if (!( $fp = fopen( $file, "r"))) { die("impossible d ouvrir le fichier XML");} 11 $data = fread($fp, filesize ( $file )) ; 12 if (! xml_parse($this >xml_parser, $data)) { die("erreur de lecture XML"); } 13 xml_parser_free($this >xml_parser); 14 } 15 16 function debutelement($parser, $name, $attrs) { } 17 function finelement($parser, $name) { } 18 function cdata($parser,$cdata){ } 19 } 20?> A. WIDLÖCHER 25 février 2004 diapo 21 sur 39
Plan de l exposé Introduction événementielle Manip o Principes Méthode d analyse Manipulations d arbre Utilisation d A. WIDLÖCHER 25 février 2004 diapo 22 sur 39
Plan de l exposé Introduction événementielle Manip o Principes Méthode d analyse Manipulations d arbre Utilisation d A. WIDLÖCHER 25 février 2004 diapo 22 sur 39
Principes Manip o Document Objet Model spécification du W3C modèle de représentation objet d un document XML permet l accès et la mise à jour d un arbre XML interface indépendante du langage et de la plate-forme API permettant la construction et la manipulation de l arbre principe de fonctionnement généralement sur la base d une lecture événementielle (SAX...) du document on construit une représentation en mémoire de la totalité de l arbre représentation objet en termes de parenté / filiation des méthodes permettent la lecture et la manipulation de l arbre-objet
l implémentation PHP de l API utilise la Gnome XML library (libxml) Manip o ne respecte pas (encore) totalement le standard résidus non-oo deprecated ici ou là expérimental n est pas installée partout en standard (--with-dom[=dir]) les attributs de classe sont implémentés par des fonctions la notation utilisée pour le noms de fonctions est conforme à la tradition PHP dans l esprit, et dans l idéal aussi proche que possible de Level 2 pleinement OO A. WIDLÖCHER 25 février 2004 diapo 22 sur 39
Avantages / Inconvénients Manip o Avantages utilisation très simple il suffit souvent d appeler une méthode pour construire l arbre-objet accès très souple à l information on peut aisément naviguer dans la représentation objet chaînages multiples avantageux pour la manipulation de l arbre des méthodes permettent de modifier la liste des fils d un nœud... Inconvénients coût en mémoire important nécessité d attendre la lecture complète de l arbre XML A. WIDLÖCHER 25 février 2004 diapo 23 sur 39
Plan de l exposé Introduction événementielle Manip o Principes Méthode d analyse Manipulations d arbre Utilisation d A. WIDLÖCHER 25 février 2004 diapo 24 sur 39
Principaux objets manipulés Manip o la classe DomDocument l intégralité du document la classe DomNode un nœud (élément, texte ou attribut) la classe DomElement un nœud de type élément la classe DomAttribute un attribut d élément A. WIDLÖCHER 25 février 2004 diapo 24 sur 39
Récupération de DomDocument Manip o la classe DomDocument représentation objet de l arbre XML on peut obtenir une instance depuis une chaîne XML avec domxml_open_mem() depuis un fichier XML avec domxml_open_file() de document vierge avec domxml_new_doc() par exemple : 1 <?php 2 $file ="menu.xml"; 3 4 if (! $document = domxml_open_file($file)) { 5 echo "Erreur pendant la lecture du fichier XML"; 6 exit ; 7 } 8?> A. WIDLÖCHER 25 février 2004 diapo 25 sur 39
Récup o de l élément racine Manip o la racine «contient» l ensemble de l arbre on utilise la méthode document_element() sur une instance de DomDocument retourne une instance de DomElement par exemple : 1 <?php 2 $file ="menu.xml"; 3 4 if (! $document = domxml_open_file($file)) { 5 echo "Erreur pendant la lecture du fichier XML"; 6 exit ; 7 } 8 9 $rootelement=$document >document_element(); 10 echo $rootelement >tagname(); 11?> A. WIDLÖCHER 25 février 2004 diapo 26 sur 39
Récup o d éléments Manip o on utilise la méthode get_elements_by_tagname() sur une instance de DomDocument ou sur une instance de DomElement retourne un tableau d éléments par exemple : 1 <?php 2 $file ="menu.xml"; 3 4 if (! $document = domxml_open_file($file)) { 5 echo "Erreur pendant la lecture du fichier XML"; 6 exit ; 7 } 8 9 $rootelement=$document >document_element(); 10 $tabrubriqueselements=$rootelement >get_elements_by_tagname("rubrique"); 11 echo " Il y a ".sizeof($tabrubriqueselements)." rubriques"; 12?> A. WIDLÖCHER 25 février 2004 diapo 27 sur 39
Récup o de contenu textuel Manip o dans le cas d un nœud qu il soit texte, attribut ou élément n a vraiment d intérêt que pour les feuilles (et attributs) on utilise la méthode get_content() sur une instance de DomNode retourne la valeur textuelle (voir ci-après pour les problèmes d encoding) 1 <?php 2 $file ="menu.xml"; 3 if (! $document = domxml_open_file($file)) { 4 echo "Erreur pendant la lecture du fichier XML"; 5 exit ; 6 } 7 $rootelement=$document >document_element(); 8 $tabrubriqueselements=$rootelement >get_elements_by_tagname("rubrique"); 9 $labelelements=$tabrubriqueselements[0] >get_elements_by_tagname("label"); 10 11 print "Le premier titre de la première rubrique est ".$labelelements[0] >get_content(); 12?> A. WIDLÖCHER 25 février 2004 diapo 28 sur 39
Récup o d attributs Manip o on utilise la méthode get_attribute() sur une instance de DomElement retourne la valeur de l attribut par exemple : 1 <?php 2 $file ="menu.xml"; 3 if (! $document = domxml_open_file($file)) { 4 echo "Erreur pendant la lecture du fichier XML"; 5 exit ; 6 } 7 $rootelement=$document >document_element(); 8 9 $tabrubriqueselements=$rootelement >get_elements_by_tagname("rubrique"); 10 $labelelements=$tabrubriqueselements[0] >get_elements_by_tagname("label"); 11 if ( trim($labelelements[0] >get_attribute("lang"))=="fr"){ 12 print "Le premier titre de la première rubrique est ".$labelelements[0] >get_content(); 13 }else{ 14 print "The first title of first section is ".$labelelements[0] >get_content(); 15 } 16?> A. WIDLÖCHER 25 février 2004 diapo 29 sur 39
Récup o d attributs (2) Manip o on peut utiliser la méthode get_attribute_node() sur une instance de DomElement retourne un objet DomNode par exemple : 1 <?php 2 $file ="menu.xml"; 3 if (! $document = domxml_open_file($file)) { 4 echo "Erreur pendant la lecture du fichier XML"; 5 exit ; 6 } 7 $rootelement=$document >document_element(); 8 9 $tabrubriqueselements=$rootelement >get_elements_by_tagname("rubrique"); 10 $labelelements=$tabrubriqueselements[0] >get_elements_by_tagname("label"); 11 $node=$labelelements[0] >get_attribute_node("lang"); 12 if ( trim($node >get_content())=="fr"){ 13 print "Le premier titre de la première rubrique est en français" ; 14 } 15?> A. WIDLÖCHER 25 février 2004 diapo 30 sur 39
Problèmes d encodage l éternelle question de fond quel encoding à la source...?... quel encoding à destination? Manip o la librairie utilisée par PHP utilise UTF-8 pour sa représentation interne et ne connaît pour ainsi dire que cet encoding on doit donc assurer «manuellement» une conversion en cas de besoin à l aide de la méthode utf8_decode() si l on souhaite récupérer du ISO-8859-1 A. WIDLÖCHER 25 février 2004 diapo 31 sur 39
Plan de l exposé Introduction événementielle Manip o Principes Méthode d analyse Manipulations d arbre Utilisation d A. WIDLÖCHER 25 février 2004 diapo 32 sur 39
Manipulations d arbres Manip o avec un simple analyseur de la famille SAX on procède principalement à la lecture de l information XML à sa transposition dans une structure de données adaptée au besoin en perdant finalement le lien avec le modèle initial en cas de modification de structure, on regénère l arbre XML «à la main» l API va plus loin en proposant un standard de représentation de l arbre en mémoire et en permettant de manipuler cette représentation objet en restant au plus près de la spécification du modèle en permettant de produire en sortie le XML correspondant à cette modification A. WIDLÖCHER 25 février 2004 diapo 32 sur 39
Modification du Manip o création de nœuds «composants» hors arbre méthodes de DomDocument... mais pas de modification effective! create_attribute() create_element() create_text_node() ajout d informations à l arbre on opère principalement au niveau du DomNode append_child() (retourne l objet child manipulable ultérieurement) insert_before() append_sibling()
modification des valeurs on opère principalement au niveau du DomNode Manip o replace_child() replace_node() (appelée sur le nœud à modifier) set_name() set_content() suppression on opère principalement au niveau du DomNode remove_child() unlink_node() (appelée sur le nœud à modifier) A. WIDLÖCHER 25 février 2004 diapo 33 sur 39
Sortie XML Manip o une fois les modifications faites sur le DomDocument on peut produire l arbre XML correspondant avec dump_file() dump_mem() html_dump_mem() 1 <?php 2 $document = domxml_new_doc("1.0"); 3 $racinehtml = $document >create_element("html"); 4 $racinehtml = $document >append_child($racinehtml); 5 $head = $document >create_element("head"); 6 $head = $racinehtml >append_child($head); 7 $title = $document >create_element("title"); 8 $title = $head >append_child($title); 9 $text = $document >create_text_node("le titre"); 10 $text = $title >append_child($text); 11 12 $document >dump_file("sortie.xml", false, true); 13?> A. WIDLÖCHER 25 février 2004 diapo 34 sur 39
Plan de l exposé Introduction événementielle Utilisation d A. WIDLÖCHER 25 février 2004 diapo 35 sur 39
Principe PHP propose une API pour les transformations basé sur Sablotron (--with-xslt-sablot) utilise également expat elle permet d appliquer un ensemble de transformations à un arbre XML en instanciant un processeur en passant à celui-ci un arbre XML et une feuille de transformation (style) A. WIDLÖCHER 25 février 2004 diapo 35 sur 39
Méthode générale les trois phases fondamentales sont les suivantes : instanciation du processeur application des transformations utilisation du résultat destruction du processeur 1 <?php 2 3 $processeurxslt = xslt_create() ; 4 5 xslt_process($processeurxslt, "menu.xml", "menuxmltofo.xsl","menu.fo"); 6 7 xslt_free ($processeurxslt); 8 9?> A. WIDLÖCHER 25 février 2004 diapo 36 sur 39
Réutilisation directe du résultat on peut aussi utiliser directement le résulat : 1 <?php 2 3 $processeurxslt = xslt_create() ; 4 5 $stringhtmlout=xslt_process($processeurxslt, 6 "menu.xml", 7 "menuxmltohtml.xsl", 8 NULL); 9 10 xslt_free ($processeurxslt); 11 12 echo $stringhtmlout; 13 14?> A. WIDLÖCHER 25 février 2004 diapo 37 sur 39
Utilisation de paramètres afin d utiliser une feuille du style du type : 1 <?xml version="1.0" encoding="iso 8859 1"?> 2 <xsl:stylesheet version="1.0" xmlns:xsl="http :// www.w3.org/1999/xsl/transform"> 3 4 <xsl:param name="lang" /> 5 6 <xsl:template match="/"><xsl:apply templates select="menu" /></xsl:template> 7 8 <xsl:template match="menu"><xsl:apply templates select="rubrique" /></xsl:template> 9 10 <xsl:template match="rubrique"> 11 <a> 12 <xsl: attribute name="href"> 13 <xsl:apply templates select="url" /> 14 </xsl : attribute > 15 <xsl:apply templates select="label[@lang=$lang]" /> 16 </a> 17 </xsl :template> 18 19 <xsl:template match="label url"> 20 <xsl:value of select="." /> 21 </xsl :template> 22 23 24 </xsl :stylesheet> A. WIDLÖCHER 25 février 2004 diapo 38 sur 39
Utilisation de paramètres on pourra procéder de la manière suivante : 1 <?php 2 3 $processeurxslt = xslt_create() ; 4 5 $args=null; 6 $params["lang"]="fr"; 7 $stringhtmlout=xslt_process($processeurxslt, 8 "menu.xml", 9 "menuxmltohtml.xsl", 10 NULL, 11 $args, 12 $params); 13 14 xslt_free ($processeurxslt); 15 16 echo $stringhtmlout; 17 18?> A. WIDLÖCHER 25 février 2004 diapo 39 sur 39