Vous êtes sur la page 1sur 46

PHP

Manipulation de XML avec DOM

A. Belad

DOM
Introduction

DOM est une API standard : Les mthodes et procdures de manipulation DOM sont exactement les mmes dans tous les langages Vous pouvez passer dun langage lautre sans avoir apprendre plusieurs noms de fonctions et plusieurs API

A. Belad

http://eusebius.developpez.com/php5dom/

DOM
Structure gnrale

DOM reprsente larbre XML sous la forme dobjets et relations entre eux Aussi bien le document que chaque noeud devient un objet part entire avec sa dfinition, ses proprits et ses mthodes Il devient alors facile de : connatre les proprits dun objet lire des objets les modifier les enregistrer dans un fichier passer dun objet lautre par une relation privilgie

A. Belad

Exemple : books.xml
<bookstore> <book category="WEB"> <title lang="en">XQuery Kick Start</title> <book category="COOKING"> <author>James McGovern</author> <title lang="en">Everyday <author>Per Bothner</author> Italian</title> <author>Kurt Cagle</author> <author>Giada De Laurentiis <author>James Linn</author> </author> <author>Vaidyanathan Nagarajan</author> <year>2005</year> <year>2003</year> <price>49.99</price> <price>30.00</price> </book> </book> <book category="WEB"> <book category="CHILDREN"> <title lang="en">Learning XML</title> <title lang="en">Harry Potter</title> <author>Erik T. Ray</author> <author>J K. Rowling</author> <year>2003</year> <price>39.95</price> <year>2005</year> </book> <price>29.99</price> </bookstore> </book>
A. Belad

Larbre DOM correspondant


Les nuds lments sont lis par des relations :
parent, child, sibling

A. Belad

Larbre DOM correspondant


Dautres relations (i.e. mthodes) :

A. Belad

1. Les objets de lextension DOM


Les objets de DOM

Les principales classes sont les suivantes :


DomNode - objet nud : - documents, lments, nuds textuels... DomDocument - objet document - (hrite de DomNode) DomElement - objet lment - (hrite de DomNode) DomAttr - objet attribut - (hrite de DomNode) DomNodeList - objet liste de DomNodes - (ce n'est pas un tableau PHP !)

A. Belad

http://eusebius.developpez.com/php5dom/

2. Lobjet document
Lobjet document reprsente larbre XML

Cration dun document Il suffit dinstancier la classe DomDocument <?php $document = new DomDocument(); ?> Chargement des donnes XML Il suffit dutiliser la mthode load() <?php $document = new DomDocument(); $document->load(monfichier.xml); ?>
http://eusebius.developpez.com/php5dom/

A. Belad

2. Lobjet document

Chargement depuis une chane XML


<?php $xml = "<livre><titre>PHP 5 avanc </titre></livre>"; $document = new DomDocument(); $document->loadXML($xml); ?>

Chargement dun fichier HTML


Il est possible de charger un fichier HTML en DOM et de le manipuler comme si ctait du XML <?php $doc = DOMDocument::loadHTMLFile("filename.html"); print $doc->saveHTML(); $doc = new DOMDocument(); $doc->loadHTMLFile("filename.html"); print $doc->saveHTML();

A. Belad

?>

http://eusebius.developpez.com/php5dom/

2. Le document DomDocument
Enregistrement d'un document XML
<?php $dom->save('nouveauFichier.xml'); ?>

Enregistrement dans une variable


<?php $chaineXML = $dom->saveXML(); //saveXML() renvoie le contenu sous //la forme dune chane de caractres ?>

Exemple : load-save-xml.php
<?php $dom = new DomDocument(); $dom->load('test.xml'); $dom->save('nouveauFichier.xml'); ?>
A. Belad

http://eusebius.developpez.com/php5dom/

10

3. Lire un document
Rechercher et rcuprer un lment

Il y a plusieurs moyens pour trouver des lments Accder l'lment racine <?php $document = new DomDocument; $document->load(fichier.xml); $racine = $document->documentElement; ?>

A. Belad

11

3. Lire un document

Accder au document depuis un nud La fonction inverse de lattribut documentElement sappelle ownerDocument Il permet de rcuprer lobjet document partir dun nud quelconque <?php $document = new DomDocument(); $document->load(monfichier.xml); $racine = $document->documentElement; $document = $racine->ownerDocument; ?>

A. Belad

12

3. Lire un document
Description dun nud

Les nuds sont des objets de la classe DomNode On peut connatre le type dun nud partir de son attribut proprit : nodeType Il retourne un entier

A. Belad

13

3. Lire un document
Description dun nud

Exemple <?php $xml = "<livre>Alice</livre>"; $document = new DomDocument(); $document->loadXML($xml); //On se place au niveau du premier nud $livre = $document->documentElement; echo $livre->nodeType; //Affiche 1 $texte = $livre->firstChild; echo $texte->nodeType; //Affiche 3 ?>

A. Belad

14

3. Lire un document
Description dun nud

Nom dun nud : deux attributs de DomNode : nodeName et tagName Exemple <?php $xml = "<livre>Alice</livre>"; $document = new DomDocument(); $document->loadXML($xml); $livre = $document->documentElement; echo $livre->nodeName; //Affiche livre echo $livre->firstChild->nodeName; //Affiche #text ?>

A. Belad

15

3. Lire un document

Contenu dun nud : Sobtient avec lattribut : nodeValue Attention, un lment na pas de valeur, ce sont ventuellement ses fils, de type nuds de texte, qui en ont Exemple : dom1.php
<?php $xml = "<livre type='conte'>Alice</livre>"; $document = new DomDocument(); $document->loadXML($xml); $livre = $document->documentElement; echo $livre->nodeName; //Affiche livre echo $livre->firstChild->nodeValue; //Affiche Alice $type = $livre->getAttributeNode('type'); echo $type->nodeValue; //Affiche conte ?>

A. Belad

16

3. Lire un document
Navigation dans larbre

Liste des nuds


Dans les recherches futures, on va rcuprer les nuds de larbre XML dans une liste : objet de type : DomNodeList On peut parcourir cette liste avec foreach() Exemple $nodeList; //objet de type DomNodeList; Foreach($nodeList as $node){ Print_r($node); } On peut galement accder un item particulier laide de la mthode : item() et dun index numrique $nodeList->item(0); //Premier nud de la liste La quantit de nuds dans une liste peut tre rcupre avec lattribut length de lobjet DomNodeList echo "Il y a ", $node->childNodes->length, " nuds fils " ;

A. Belad

17

3. Lire un document
Navigation dans larbre

Nuds fils
La liste des nuds fils dun nud peut tre connue via lattribut : childNodes du nud pre. Lobjet renvoy est un objet de type DomNodeList Exemple : dom-fils.php
<?php $xml = "<livre><titre>PHP 5</titre><auteur>E. D</auteur><auteur>C. PdG</auteur></livre>"; $document = new DomDocument(); $document->loadXML($xml); $livre = $document->documentElement; //Affichage des fils de $livre foreach($livre->childNodes as $node){ if($node->nodeType ==XML_ELEMENT_NODE){ echo 'Balise <b>', $node->tagName, '</b><br>'; echo 'Contenu : <b>'; echo utf8_decode($node->firstChild->nodeValue),'</b><br>'; } } ?>

A. Belad

18

3. Lire un document
Navigation dans larbre

Nuds fils
Il est possible daccder directement au premier ou au dernier nud fils laide des attributs : firstChild et lastChild Exemple : dom-fils2.php
<?php $xml = "<versions> <version>3</version> <version>4</version> <version>5</version> </versions>"; $document = new DomDocument(); $document->loadXML($xml); $versions = $document->documentElement; //On rcupre le premier fils $trois = $versions->firsChild; //On rcupre le dernier fils $cinq = $versions->lastChild; ?>

A. Belad

19

Nuds fils
On peut tester la prsence de nuds fils laide de la mthode : hasChildNodes() Exemple : dom-fils3.php <?php $xml = "<versions> <version>3</version> <version>4</version> <version>5</version> </versions>"; $document = new DomDocument(); $document->loadXML($xml); $versions = $document->documentElement; //Affichage des fils de $versions if($versions->hasChildNodes()){ foreach($versions->childNodes as $node){ if($node->nodeType == XML_ELEMENT_NODE){ echo $node->tagName, ' : '; echo utf8_decode($node->firstChild->nodeValue), '<br>'; }}} ?>

3. Lire un document
Navigation dans larbre

Nud parent Le nud parent dun nud peut tre connu via lattribut parentNode du nuds fils. Il ,renvoie un objet de type DomNode $parent $fils = $parent->firstChild; $parent = $fils->parentNode;

A. Belad

21

3. Lire un document
Navigation dans larbre

Nuds frres Deux possibilits : - Soit remonter au pre, puis lister les fils - Soit plus simplement : via les attributs previousSibling et nextSibling Print_r($node->childNode->item(0)); Print_r($node->childNode->item(1)); //est quivalent : $node = $node->childNodes->item(0); Print_r($node); Print_r($node->nextSibling);

A. Belad

22

3. Lire un document
Recherche dlment par le nom

DomDocument::getElementsByTagName() Recherche dans tout le document DomElement::getElementsByTagName() Recherche dans les descendants de l'lment considr Ces fonctions retournent un objet DomNodeList

A. Belad

23

3. Lire un document
Exemple de getElementsByTagName()
<?php $dom = new DomDocument(); $dom->load("test.xml"); $listePays = $dom->getElementsByTagName('pays'); foreach($listePays as $pays) echo $pays->firstChild->nodeValue . "<br />"; echo "---<br />"; $europe = $dom->getElementsByTagName('europe')->item(0); $listePaysEurope = $europe->getElementsByTagName('pays'); foreach($listePaysEurope as $pays) echo $pays->firstChild->nodeValue . "<br />"; ?>
A. Belad

24

3. Lire un document
getElementsByTagName.php

Rsultat : France Belgique Espagne Japon Inde Etats-Unis Canada Tunisie Cameroun --France Belgique Espagne
25

A. Belad

3. Lire un document
Lire les attributs

Modifier le fichier XML ( la main) pour ajouter des attributs donnant le rgime politique des pays cits (on suppose que la DTD aura galement t modifie en consquence, si l'on veut profiter de la validation) : <?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?> <!DOCTYPE continents SYSTEM "test.dtd"> <continents> <europe> <pays regime="republique">France</pays> <pays regime="monarchie constitutionnelle">Belgique</pays> <pays regime="monarchie constitutionnelle">Espagne</pays> </europe> <asie> <pays regime="empire">Japon</pays> <pays>Inde</pays> </asie> </continents>
26

A. Belad

3. Lire un document
Lire les attributs par getAttribute : getAttribute.php
<?php $listePays = $dom->getElementsByTagName("pays"); foreach($listePays as $pays) { echo $pays->nodeValue; if ($pays->hasAttribute("regime")) { echo " - " . $pays->getAttribute("regime"); } echo "<br />"; } >

Pour viter les erreurs, vrifier l'existence de l'attribut avec la fonction hasAttribute() qui prend aussi le nom de l'attribut en paramtre, et qui renvoie un boolen qui dit si l'attribut est prsent ou pas
27

A. Belad

3. Lire un document
Lire par getAttribute

Rsultat France - republique Belgique - monarchie constitutionnelle Espagne - monarchie constitutionnelle Japon - empire Inde

A. Belad

28

3. Lire un document
Lire les nuds textuels

On l'a dj vu, on peut rcuprer la valeur d'un nud textuel avec l'attribut nodeValue <?php $pays = $dom->getElementsByTagName("pays"); foreach($pays as $c) { echo $c->nodeValue . " " . $c->firstChild->nodeValue; echo "<br />"; } ?>

A. Belad

29

3. Lire un document
Lire les nuds textuels

Rsultat : France France Belgique Belgique Espagne Espagne Japon Japon Inde Inde

A. Belad

30

4. Modifier un document
Modification
Voyons maintenant comment modifier les diffrents lments d'un document XML dj existant Crer un noeud

La mthode DomDocument::createElement permet trs simplement de crer des lments XML, en passant en paramtre le nom du nud Crer un lment <?php $nouveauPays = $dom->createElement("pays"); ?> Crer un nud textuel : si on veut ajouter un nud textuel cet

lment (pour donner un nom de pays par ex.) : createTextNode


<php $nomPays = $dom->createTextNode("Royaume-Uni"); ?>
A. Belad

31

4. Modifier un document

Crer un nud par copie dun nud existant <?php $paysIdentique = $pays->cloneNode(); ? Cette mthode accepte un argument facultatif, un boolen (FALSE par dfaut). S'il est TRUE, tout les nuds fils seront copis galement, et donc toute une partie de l'arborescence peut tre duplique par ce biais.

A. Belad

32

4. Modifier un document
Modifier un attribut Il nous faut maintenant ajouter un attribut notre nouveau nud, afin de prciser le rgime politique : utiliser setAttribute Cration ou modification d'attribut <?php $nouveauPays->setAttribute("regime", "monarchie constitutionnelle"); ?> On peut supprimer un attribut avec DomElement::removeAttribute (avec le nom de l'attribut en paramtre)

A. Belad

33

4. Modifier un document
Insrer un nud dans le document

Nous avons vu comment crer les lments et les nuds textuels, mais encore faut-il les placer dans le document XML, et au bon endroit L'insertion se fait par la mthode DomNode::appendChild qui ajoute le nud pass en paramtre la liste des enfants du nud sur lequel il est appel

Insertion de nouveaux lments <?php $nouveauPays->appendChild($nomPays); $europe = $dom->getElementsByTagName("europe")->item(0); $europe->appendChild($nouveauPays); ?> ajoute le nud textuel $nomPays au nud $nouveauPays, et ajoute ensuite celui-ci au nud "europe"
34

A. Belad

4. Modifier un document
Supprimer un nud

Utiliser DomNode::removeChild en l'appelant sur le parent du nud supprimer et en passant en paramtre une rfrence sur le nud supprimer Tous les descendants du nud supprim seront galement extermins <?php $europe->removeChild($nouveauPays); ?>

A. Belad

35

6. Recherche Xpath
Initialisation

Le moteur DOM permet de grer des requtes Xpath Il utilise un objet pour grer la requte Cet objet est de la classe DomXpath qui attend un document DOM en argument $document = new DomDocument(); $document->loadXml($xml) $xpath = new DomXpath($document);

A. Belad

36

6. Recherche Xpath
Lancer une requte Xpath

Pour faire une recherche, il faut faire appel la mthode query() <?php $xml = file_get_contents(fichier.xhtml); $xml = utf8_encode($xml); $document = new DomDocument(); $document->loadXml($xml); $xpath = new DomXpath($document); //rechercher tous les formulaires envoyer $result = $xpath->query("/html/body//form[@action=post]"); ?>

A. Belad

37

6. Recherche Xpath
Lancer une requte Xpath

Par dfaut, la recherche est faite partir de llment racine On peut toutefois prciser le nud pour la recherche $requete ="form[action=post]"; $reference = $document->documentElement->lastChild; $result = $xpath->query($requete, $reference); Le rsultat renvoy est un objet liste de nuds DOM classiques $document = new DomDocument(); $document->loadXml($xml); $xpath = new DomXpath($document); //recherche tous les formulaires envoyer avec la mthode POST $result = $xpath->query("/html/body//form[@action=post]"); echo "Il y a ", $result->length, " formulaire(s) en POST";
38

A. Belad

6. Recherche Xpath
Lancer une requte Xpath

Soit le fichier XML suivant : php5avance.xml <?xml version="1.0" encoding="utf-8"?> <livre> <titre>PHP 5 avanc 5me dition</titre> <auteur>Eric Daspet</auteur> <auteur>Cyril Pierre de Geyer</auteur> <preface>Damien Sguy</preface> <relecteur>Hugo Hamon</relecteur> </livre>

A. Belad

39

On cherche rcuprer tous les nuds auteur et afficher leur contenu texte dans une liste non ordonne HTML : dom-xpath1.php
<?php $xml = file_get_contents('php5avance.xml'); $xml = utf8_encode($xml); $document = new DomDocument(); $document->preserveWhiteSpace = false; $document->loadXML($xml); $xpath = new DomXpath($document); //recherche tous les noeuds <auteur> $result = $xpath->query("/livre/auteur"); echo "Il y a ", $result->length, "auteur(s) pour ce livre :"; echo "<ul>\n"; foreach($result as $auteur) { echo "<li>$auteur->nodeValue</li>\n"; } echo "</ul>\n;" ?>

7. Validation
Validation par rapport une DTD

Il est possible de vrifier la conformit dun document avec un fichier grce la mthode boolenne validate() Exemple : <?php $dom = new DOMDocument; $dom->Load('book.xml'); if ($dom->validate()) { echo "Ce document est valide !\n"; } ?>

A. Belad

http://eusebius.developpez.com/php5dom/

41

Validation
Exemple : test2.xml
<?xml version="1.0" encoding="ISO8859-1" standalone="no" ?> <!DOCTYPE continents SYSTEM "test.dtd"> <continents> <europe> <pays>France</pays> <pays>Belgique</pays> <pays>Espagne</pays> </europe> <asie> <pays>Japon</pays> <pays>Inde</pays> </asie> <amerique> <pays>Etats-Unis</pays> <pays>Canada</pays> </amerique> <afrique> <pays>Tunisie</pays> <pays>Cameroun</pays> </afrique> </continents>

A. Belad

42

Validation : Exemple
test2.dtd
<!ELEMENT continents (europe?, asie?, amerique?, afrique?)> <!ELEMENT europe (pays*)> <!ELEMENT pays (#PCDATA)> <!ELEMENT asie (pays*)> <!ELEMENT amerique (pays*)> <!ELEMENT afrique (pays*)>

Exemple : dom-validate2.php

A. Belad

43

8. Transformation XML par XSLT


Initialisation

Le moteur XSLT sutilise via un objet propre, un peu comme Xpath Il faut donc commencer par instancier un objet de la classe XSLTProcessor $moteurXslt = new xsltProcessor(); Ceci se fait via la mthode importStylesheet() qui accepte un document DOM en argument $moteurXslt = new xsltProcessor(); $style = new domDocument(); $style->load(style.xsl); $moteurXslt->importStylesheet($style);
44

Chargement de la feuille de style

A. Belad

8. Transformation XML par XSLT


Transformation

Elle se fait via la mthode transformToXml() Elle accepte un document DOM en argument et renvoie le XML produit $moteurXslt = new XSLTProcessor(); $style = new domDocument(); $style->load(style.xsl); $moteurXslt->importStylesheet($style); $source = new DomDocument(); $source->load(source.xml); echo $moteurXslt->transformToXML($source); Attention : aller dans php.ini et enlever le ; devant extension=php_xsl.dll
45

A. Belad

2. Le document DomDocument
Import depuis SimpleXML

Si vous avez utilis SimpleXML pour lire rapidement un fichier et que vous souhaitez faire quelques manipulations DOM, il est possible dimporter lobjet SimpleXML pour construire un objet DOM de manire transparente <?php $s = SimpleXML_load_file(fichier.xml); $dom = dom_import_simplexml($s); print $dom->ownerDocument->saveXML(); ?> ownerDocument : retourne la racine du document saveXML() : cre une reprsentation XML depuis la reprsentation DOM
http://eusebius.developpez.com/php5dom/ 46

A. Belad