Programmation PHP/DOMDocument

Un livre de Wikilivres.

Introduction[modifier | modifier le wikicode]

Une des recherches majeures du développeur a toujours été de chercher à séparer les langages de programmation, clarifiant ainsi ses scripts et simplifiant sa tâche. Ainsi, il est possible d'enregistrer son CSS dans des fichiers externes comportant l'extension .css, de séparer le javascript du HTML en l'enregistrant dans des fichiers .js.

Il reste cependant le problème de la séparation du PHP et du XHTML. La librairie DOMDocument va repousser ces limites.

Qu'est-ce que DOMDocument ?[modifier | modifier le wikicode]

DOMDocument est une librairie de fonctions apparue avec PHP5[1] et activée par défaut. Elle permet de concevoir des pages HTML sous forme d'objets.

Les avantages et les inconvénients[modifier | modifier le wikicode]

  • Concevoir des pages HTML par cette méthode permet d’annihiler un problème majeur de la programmation procédurale : l'édition du code n'est plus en fonction de sa position dans le script. Pour être plus clair, chaque balise jusqu'à la DTD peut être modifiée à tout moment dans l'objet HTML.
  • Il est possible d'enregistrer la page HTML dans un fichier sans l'afficher.

mais...

  • Le code est plus long à éditer.

Principe du DOM[modifier | modifier le wikicode]

Cette librairie présente de nombreuses similitudes avec le javascript aussi bien dans le fonctionnement que dans le nom de ses fonctions.

Le DOM (Document Object Model) est basée sur un système de nodes. Un node est un élément qui est - soit une balise (nodes Tag) - soit du texte - soit un attribut de balise Les nodes sont liés par un système hiérarchique :

<p>Ce texte est <strong>important</strong></p>

On dit alors que le node Tag <strong> est fils du node <p> Le node texte "Ce texte est" est également fils de <p> qui est parent du node texte.

Il existe un certain nombre de classes prédéfinies : DOMDocument, DOMNode, DOMElement, DOMText, DOMAttr, DOMList... Certaines sont très simples, d'autres possèdent des fonctionnalités très avancées.

Importer une page préexistante[modifier | modifier le wikicode]

Il est possible d'importer une page HTML. Cela simplifiera considérablement la tâche du programmeur qui n'aura qu'à apporter les modifications nécessaires avant de l'afficher ou de réenregistrer la page. Voici le code important la page.

<?php
$doc = DOMDocument::loadHTMLFile("fichier.html");

La variable $doc contient donc un objet DOMDocument avec toutes les balises sous formes de nodes. Il est maintenant possible d'accéder aux nodes par le biais de fonctions préexistantes.

NB : il est également possible d'avoir recours au code suivant.

<?php
$doc = new DOMDocument();
$doc->loadHTMLFile("fichier.html");


Il est également possible d'importer le code à partir d'une chaîne de caractères :

<?php
$code = "<html><head></head><body></body></html>";
$doc = new DOMDocument();
$doc->loadHTML( $code );

Enregistrer une page[modifier | modifier le wikicode]

Un des grands avantages de cette librairie est la capacité à enregistrer la page générée dans un fichier pour un affichage ultérieur. Il suffit d'avoir recours au code suivant :

$doc->saveHTMLFile("fichier.html");


Si vous voulez l'afficher, il vous suffit d'exécuter la fonction suivante :

<?php
echo $doc->saveHTML();

La méthode retourne une chaîne de caractères que la fonction echo affiche.

Logo

Le résultat n'est pas en Unicode, donc les lettres avec diacritiques seront mal affichées par défaut, en français : àâçéèêëîïôöüù. Cela peut aussi générer un Warning: DOMDocumentFragment::appendXML(): Entity: line 1: parser error : Input is not proper UTF-8, indicate encoding !

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr-FR">
	<head>
		<meta http-equiv="Content-type" content="text/html; charset=UTF-8"/>
	</head>
	<body>
<?php
$code = 'Les àâçéèêëîïôöüù';
echo $code;  // affichage normal

$page = new DOMDocument();
$page->loadHTML($code);
echo $page->saveHTML();  // Les à âçéèêëîïôöüù

// Solution
$page2 = new DOMDocument();
$page2->loadHTML(utf8_decode($code));
echo $page2->saveHTML();  // Les àâçéèêëîïôöüù
?>
	</body>
</html>

La classe DOMNode[modifier | modifier le wikicode]

Les classes DOMElement, DOMText et DOMAttribute sont dérivées de cette classe. Ainsi, les méthodes et propriétés présentées ici seront disponibles pour leurs classes filles.

Attention : un node une fois créé ne se trouve pas dans le document. Ajouter un node va se dérouler en deux étapes : - on crée le node - on l'insère dans le node parent ou à la racine du document.

Voici les propriétés accessibles à tous les nodes :

$node->nodeType // Type de node. Vaut 1 pour un élément XML, 3 pour un texte
$node->childNodes //Retourne un objet NodeList qui contient tout les éléments enfants de ce node
$node->firstChild //Retourne le premier node enfant
$node->lastChild // Retourne le dernier node enfant
$node->previousSibling // Retourne le node juste avant celui-ci
$node->nextSibling // Retourne le node juste après celui-ci

Les méthodes sont les suivantes

  • AppendChild

Le node $enfant devient enfant de $node

$node->appendChild( $enfant );
  • RemoveChild

Supprime le node $enfant du node $node

$node->removeChild( $enfant );

La classe DOMElement[modifier | modifier le wikicode]

  • Les éléments possèdent les propriétés suivantes :
$node->tagName // par exemple "p" pour un paragraphe. Sa valeur ne peut être modifiée

Attention : seules les principales propriétés sont présentées. Si vous voulez en avoir la liste complète, vous pouvez consulter la documentation de référence sur http://php.net/manual/fr/class.domnode.php.


  • Et les méthodes suivantes :

- Méthodes d'attributs

$node->hasAttribute(); //Renvoie true si il possède des attributs
$node->getAttribute("name"); //Retourne la valeur de l'attribut
$node->removeAttribute("name"); //Supprime l'attribut ''name''
$node->setAttribute("name","value"); //Modifie un attribut
$node->getAttributeNode ("name" ); //Retourne un objet DOMAttr

- Autres méthodes

$newNode = $node->cloneNode(); //duplique un élément

$nodeList = $node->getElementsByTagName("strong");

Cette fonction retourne un objet nodeList qui contient une liste des balises <strong> enfants du node. Pour récupérer le n+1ème node de la liste, il suffit d'avoir recours à la méthode de l'objet nodeList suivante :

$strong5 = $nodeList->item(4); //Sélectionne la 5e balise <strong>

L'attribut length donne le nombre d'éléments de la liste. Exemple :

for ($i=0; $i<$nodeList->length; $i++)
{
   echo $nodeList->item( $i )->tagName;
}

Comme vous le savez, tagName retourne le nom de la balise. Ici, le code retournera "strongstrongstrong…". En effet, seuls les nodes strong ont "été sélectionné. Comme vous avez pu le remarquer, il est possible d'exécuter plusieurs méthodes et propriétés en même temps. Voici l'ordre d'exécution :

- La méthode item($i) est exécutée et retourne un nodeTag.

- La propriété tagName du node est appelée. Attention : c'est celle de l'objet retourné.

- La fonction echo affiche le nom de la balise retournée par la propriété tagName.

La classe DOMText[modifier | modifier le wikicode]

La classe DOMText contient l'unique propriété suivante :

$node->wholeText

Elle n'est accessible qu'en lecture seule.

La classe DOMText admet deux méthodes :

/* Retourne true si la chaîne de caractère contient des espaces */
$node->isWhitespaceInElementContent();

/* Retourne dans $end un objet Text qui contient la fin du texte de $node. $node ne contiendra plus que les 5 premiers caractères de sa chaîne */

$end = $node->splitText(5)

Exemple :

<?php
$doc = new DOMDocument();
$text = $doc->createTextNode("Je suis celui qui est");
$text2 = $text->splitText(7);

echo $text->wholeText."<br />";
echo $text2->wholeText

Ce code retournera "je suis<br /> celui qui est"

La classe DOMAttr[modifier | modifier le wikicode]

La classe DOMAttr est comme son nom l'indique un attribut, qui est donc dépendant de la balise. Elle contient les propriétés suivantes :

$node->name // Nom de l'attribut
$node->value // Valeur de l'attribut

/* Nom de la balise qui contient l'attribut. La valeur retournée est un objet DOMElement */
$node->ownerElement

Seule la propriété value n'est pas en lecture seule, c'est à dire qu'il est possible d'avoir recours au code suivant :

$node->value = "maValeur";

Accéder à un node[modifier | modifier le wikicode]

Il existe plusieurs modes de recherche du node. Il est par exemple possible de le sélectionner par son id :

$node = $doc->getElementById("sonId"); //Retourne un objet node

Sachant qu'il ne peut y avoir qu'un node possédant l'id recherché, la méthode retournera un objet node au lieu d'un objet nodeList.

Il est cependant possible de récupérer une liste de nodes en les sélectionnant par leur nom de balise. Évidemment, seuls les nodes Tag peuvent être sélectionnés.

$nodeList = $doc->getElementsByTagName("acronym"); //Sélectionne toutes les balises <acronym>

Comme nous l'avons déjà dit, il faut, pour récupérer un node particulier de la liste, utiliser la méthode suivante :

$acronym5 = $nodeList->item(4); //Sélectionne le 5e node de la liste;

XML[modifier | modifier le wikicode]

// Création
$xml = new DOMDocument("1.0", "ISO-8859-15");
$xml_node1 = $xml->createElement("Node_1");
$xml_node2 = $xml->createElement("Node_2", "Feuille");
$xml_node2->setAttribute("Attribut_1", "Valeur_1");
$xml_node1->appendChild($xml_node2);
$xml->appendChild($xml_node1);
$xml->save('Fichier_1.xml');

// Lecture
$xml = new DomDocument;
$xml->load('Fichier_1.xml');
$nodes = $xml->getElementsByTagName("Node_2");
var_dump($nodes);

Références[modifier | modifier le wikicode]

  1. http://php.net/manual/fr/book.dom.php


Voir aussi[modifier | modifier le wikicode]