Aller au contenu

Programmation PHP/DOMDocument

Un livre de Wikilivres.

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 XML (incluant le HTML). La bibliothèque DOMDocument va repousser ces limites.

Qu'est-ce que DOMDocument ?

[modifier | modifier le wikicode]

DOMDocument est une bibliothèque 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 bibliothèque 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é sur un système de nodes (nœuds). 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 bibliothèque 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 nœud une fois créé ne se trouve pas dans le document. Ajouter un nœud va se dérouler en deux étapes :

  1. on crée le nœud
  2. on l'insère dans le nœud parent ou à la racine du document.

Voici les propriétés accessibles à tous les nœuds :

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

Les méthodes sont les suivantes :

AppendChild
Le nœud $enfant devient enfant de $node
$node->appendChild( $enfant );
RemoveChild
Supprime le nœud $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 nœud. Pour récupérer le n+1ème nœud 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 nœuds 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 nœud 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 nœud

[modifier | modifier le wikicode]

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

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

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

Il est cependant possible de récupérer une liste de nœuds en les sélectionnant par leur nom de balise. Évidemment, seuls les nœuds 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 nœud particulier de la liste, utiliser la méthode suivante :

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

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');

$fields = $xml->getElementsByTagName('fields');
foreach ($fields as $field) {
    /** @var DOMElement|DomText $fieldChild */
    foreach ($field->childNodes as $fieldChild) {
        var_dump($fieldChild->nodeValue);
    }
}
  1. http://php.net/manual/fr/book.dom.php