23.2. TD Utilisation de XML

23.2.1. Document bien formé

Pour mettre en évidence les règles que doit respecter un document XML pour être bien formé nous allons utiliser l´extension DOM présente dans PHP 5. Comme son nom le laisse deviner elle implémente l´API DOM de niveau 2. Nous allons utiliser l´objet DOMDocument et plus particulièrement ses méthodes load() et saveXML().

23.2.2. DOMDocument

L´objet DOMDocument va nous permettre d´exploiter un document XML. Il dispose de méthodes pour lire, créer ou modifier un document XML.

23.2.2.1. Méthode load()

Cette méthode va nous permettre de "charger" notre document XML dans l´objet DOMDocument à partir d´un fichier. Comme tout parseur lors de l´utilisation de cette méthode il vérifie que le document soit bien formé

23.2.2.2. Méthode saveXML()

Cette méthode3 renvoie le document XML sous forme d´une chaîne et va nous permettre d´afficher le document.

23.2.2.3. Affichage d´un document

Dans cet exemple nous avons plusieurs points qui rendent le document exemple1.xml mal formé.

<?xml version="1.0" encoding="utf-8"?>
<exemple1>
    <baliseSeule>cet élément n´a pas de balise de fin.
    <element VideIncorrect parmetre="1">
    <element parametreIncorrect=test>La déclaration du paramètre est incorrecte</element>
    <element1>imbrication<element2>incorrecte de ces 2 éléments</element1></element2>
    <element>qui dispose d´une entité caractère prédéfinie non échappée &.</element>
    <balise avec des caractères interdits/>
</exemple1>

Créez le fichier exemple1.php que vous placez dans l´arborescence de votre serveur Web.

<?php
$document = new DOMDocument();
$document->load(´exemple1.xml´);
echo
$document->saveXML();
?>

Vous appelez ensuite la page exemple1.php dans votre navigateur. Nous obtenons le résultat suivant :

Warning: DOMDocument::load() [domdocument.load]: Specification mandate value for attribute VideIncorrect in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 4 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: attributes construct error in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 4 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: Couldn't find end of Start Tag element line 4 in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 4 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: AttValue: " or ' expected in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 5 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: attributes construct error in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 5 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: Couldn't find end of Start Tag element line 5 in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 5 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: Opening and ending tag mismatch: baliseSeule line 3 and element in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 5 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: Opening and ending tag mismatch: element2 line 6 and element1 in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 6 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: Opening and ending tag mismatch: element1 line 6 and element2 in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 6 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: xmlParseEntityRef: no name in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 7 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: Specification mandate value for attribute avec in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 8 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: attributes construct error in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 8 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Warning: DOMDocument::load() [domdocument.load]: Couldn't find end of Start Tag balise line 8 in file:///C:/Program%20Files/EasyPHP%203.0/www/exemple1.xml, line: 8 in C:\Program Files\EasyPHP 3.0\www\exemple1.php on line 3

Corrigez les différentes erreurs pour que votre document soit bien formé. Nous obtenons alors :

cet élément n´a pas de balise de fin. La déclaration du paramètre est incorrecte imbrication incorrecte de ces 2 éléments qui dispose d´une entité caractère prédéfinie non échappée &.

Pour rendre le document plus lisible nous allons ajouter la commande suivante au début du fichier exemple.php.

header("Content-type: text/xml");

Nous indiquons à notre navigateur que le document envoyé est un document XML Si le navigateur gère le XML l´affichage sera beaucoup plus clair:

23.2.3. Les définitions de type de documents

Un document bien formé garanti que le parseur XML utilisé sera capable de le lire. La définition de type de documents va permettre de s´assurer que le document transmis a du sens pour le processeur XML. Nous allons commencer par un exemple simple qui va représenter les informations liées à un livre.

23.2.3.1. DTD d´un livre

Nous souhaitons que le document XML résultant dispose des informations suivantes:

  • le titre

  • l´auteur

  • le code ISBN

  • une description

  • le type de livre

  • des commentaires de lecteurs. Fonction de ces éléments nous allons définir notre DTD.

<!-- DTD de présentation d´un livre. -->

<!ELEMENT livre (titre, auteur, type, description, commentaire*)>
<!ATTLIST livre ISBN CDATA #REQUIRED>
<!ELEMENT titre (#PCDATA)>
<!ELEMENT auteur (#PCDATA)>
<!ELEMENT type (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT commentaire (#PCDATA)>

Placez cette DTD dans le fichier livre.dtd. Nous allons ensuite définir un premier document XML valide.

<?xml  version=´1.0´ encoding=´UTF-8´?>
<!DOCTYPE  livre SYSTEM "livre.dtd">
<livre  ISBN="2-99999-123-4" >
    <titre>Le XML rapide.</titre>
    <auteur>Auteur du livre</auteur>
    <type>Documentation technique</type>
    <description>Cet ouvrage explique les fondements du XML.</description>
    <commentaire>Bon rapport qualité prix.</commentaire>
    <commentaire>Bonne explication des bases.</commentaire>
</livre>

Enregistrez ce document dans le fichier livre1.xml. Pour valider notre document nous allons utiliser la méthode validate() de l´objet DOMDocument. Cette méthode utilise la définition présente dans le document XML pour valider ce dernier. Créez ensuite un fichier PHP livre.php, avec le code suivant:

<?php
$document = new DOMDocument;
$document->load("livre1.xml");
echo ($document->validate())?"Le document est valide.":"Le document n'est pas valide.";
?>

Nous obtenons un message qui confirme la validité du document.

23.2.4. Tests de validité

23.2.4.1. Cardinalité des éléments

Nous allons maintenant considérer que l´élément description est facultatif. Supprimez-le du document XML et actualisez la page livre.php. Vous obtenez le message d´erreur suivant:

Si l´on ne précise rien dans la DTD l´élément doit être obligatoirement présent. Pour rendre la description facultative nous allons modifier la DTD de notre document. Nous plaçons le symbole "?" derrière l´élément description. Une fois modifiée la DTD se présente comme suit:

....
<!ELEMENT livre (titre, auteur, type, description?, commentaire*)>
...

Cette fois notre document est valide.

23.2.4.2. Séquence des éléments

À présent modifiez le fichier livre.xml de façon à placer l´élément auteur avant l´élément titre.

Lorsque nous affichons la page livre.php avec ce nouveau document nous obtenons un message d´erreur puisque les éléments ne sont pas dans l´ordre défini dans la DTD.

23.2.4.3. Contenu mixte

Reprenons notre exemple et faisons évoluer le modèle en fonction du type. Dans le cas de romans nous souhaitons structurer la description. Nous ajoutons pour cela 2 balises enfants à description et obtenons la DTD suivante:

...
<!ELEMENT description (#PCDATA|epoque|resume)*>
<!ELEMENT epoque (#PCDATA)>
<!ELEMENT resume (#PCDATA)>
...

Il est alors possible d´ajouter à la description classique ces 2 éléments.On parle alors de contenu mixte.

<?xml version=´1.0´ encoding=´UTF-8´?> <!DOCTYPE livre SYSTEM "livre.dtd"> <livre ISBN="2-99999-123-4" > <titre>Mon roman</titre> <auteur>Auteur du livre</auteur> <type>roman</type> <description> description du livre, <epoque>de nos jours</epoque> <resume>Resumé du roman</resume> </description> </livre>

23.2.4.4. Les entités

Nous allons créer une entité qui comprend le titre du livre:

<?xml  version=´1.0´  encoding=´UTF-8´?>
<!DOCTYPE  livre  SYSTEM  "livre.dtd"
[
<!ENTITY  titreLivre  "Le  XML  rapide">
]>

<livre  ISBN="2-99999-123-4"  >  <titre>&titreLivre;</titre>
<auteur>Auteur  du  livre</auteur>
<type>Documentation  technique</type>
<description>&titreLivre;  explique  les  fondements  du  XML.</description>
<commentaire>&titreLivre;  a  un  bon  rapport  qualité  prix.</commentaire>
<commentaire>Bonne  explication  des  bases.</commentaire>
</livre>

Modifiez ensuite le fichier livre.php avec le code suivant:

<?php
header("Content-type:  text/xml");
$document = new DOMDocument;
$document->load("livre1.xml");
if($document->validate())
{
    echo $document->saveXML();
}
else{
    echo  "Le  document  n´est  pas  valide.";
}
?>

Nous obtenons le résultat suivant:

23.2.5. XSD (XML Schema Definition)

23.2.5.1. Schéma d´un livre

Un schéma XML va nous permettre tout comme une DTD de contrôler la validité d´un document XML. Commençons par définir le schéma pour notre exemple de livre:

<?xml  version=´1.0´  encoding=´UTF-8´?>

<xsd:schema  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="livre" type="livreType"/>
    <xsd:complexType name="livreType">
        <xsd:sequence>
            <xsd:element name="titre" type="xsd:string"/>
            <xsd:element name="auteur" type="xsd:string"/>
            <xsd:element name="type" type="xsd:string"/>
            <xsd:element name="description" type="xsd:string"/>
            <xsd:element name="commentaire" type="xsd:string" minOccurs="0"
            maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="ISBN" type="xsd:string"/>
    </xsd:complexType>
</xsd:schema>

Enregistrez ce schéma dans le fichier livre.xsd. Le fichier livre1.xml va nous servir pour tester notre schéma. La méthode schemaValidate() de l´objet DOMDocument va nous permettre de valider le document.

<?xml  version="1.0" encoding="UTF-8"?>
<livre  ISBN="2-99999-123-4" >
    <titre>Le Xml rapide</titre>
    <auteur>Auteur du livre</auteur>
    <type>Documentation technique</type>
    <description>Cet ouvrage explique les fondements du XML.
    </description>
    <commentaire>Bon rapport qualité prix.</commentaire>
    <commentaire>Bonne explication des bases.</commentaire>
</livre>

Créez ensuite un fichier PHP livreXSD.php, avec le code suivant:

<?php
header("Content-type:  text/xml");
$document = new DOMDocument;
$document->load("livre1.xml");
echo ($document->schemaValidate("livre.xsd"))?"Le document est valide." :"Le document n´est pas valide.";
?>

L’appel de cette page dans noter navigateur nous permet de vérifier que notre document est bien valide.

23.2.5.2. Tests de validité

Comme dans l´exemple avec la DTD nous souhaitons maintenant rendre la description facultative. Donc supprimez l´élément description du document et faites le test de validité. Nous obtenons alors un message d´erreur qui nous indique l´absence de l´élément. Pour régler ce problème, nous modifions le schéma de la façon suivante:

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element  name="livre"  type="livreType"/>
<xsd:complexType  name="livreType">
    <xsd:sequence>
        <xsd:element  name="titre"  type="xsd:string"/>
        <xsd:element  name="auteur"  type="xsd:string"/>
    <xsd:element  name="type"  type="xsd:string"/>
    <xsd:element  name="description"  type="xsd:string"  minOccurs="0"/>
    <xsd:element  name="commentaire"  type="xsd:string"  minOccurs="0"  maxOccurs="unbounded"/>
    </xsd:sequence>
    <xsd:attribute  name="ISBN"  type="xsd:string"/>
</xsd:complexType>
</xsd:schema>

L´ajout de l´attribut minOccurs="0" permet d´indiquer que l´élément est facultatif.

Enrichissons maintenant l´élément description en lui donnant un contenu mixte. Il pourra ainsi contenir du texte, un élément epoque et un élément resume. Nous apportons les modifications suivantes au document XML:

<?xml  version=´1.0´  encoding=´UTF-8´?>
<!DOCTYPE  livre  SYSTEM  "livre.dtd">
<livre  ISBN="2-99999-123-4"  >
    <titre>Mon  roman</titre>
    <auteur>Auteur du livre</auteur>
    <type>roman</type>
    <description>description du livre,
        <epoque>de nos jours</epoque>
        <resume>Resumé du roman</resume>
    </description>
</livre>

Si vous effectuez la validation après cette modification l´erreur qui remonte vous indique que l´élément est de type simple. De fait s´il est de type simple, il ne peut pas contenir d´autres éléments. Nous modifions le schéma pour prendre ce point en considération:

<?xml  version=´1.0´  encoding=´UTF-8´?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="livre" type="livreType"/>
<xsd:complexType name="livreType">
    <xsd:sequence>
        <xsd:element name="titre" type="xsd:string"/>
        <xsd:element name="auteur" type="xsd:string"/>
        <xsd:element name="type" type="xsd:string"/>
        <xsd:element name="description" minOccurs="0">
            <xsd:complexType mixed="true">
                <xsd:sequence>
                    <xsd:element name="epoque" type="xsd:string" minOccurs="0"/>
                    <xsd:element name="resume" type="xsd:string" minOccurs="0"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
        <xsd:element name="commentaire" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
    <xsd:attribute name="ISBN" type="xsd:string"/>
</xsd:complexType>
</xsd:schema>

Nous avons donc passé l´élément description en type complexe. L´attribut mixed="true" indique qu´il a un contenu mixte. Notez que les 2 éléments enfants sont facultatifs.

Nous pouvons donc écrire maintenant:

<?xml  version="1.0" encoding="UTF-8"?>
<livre  ISBN="2-99999-123-4" >
    <titre>Le Xml rapide</titre>
    <auteur>Auteur du livre</auteur>
    <type>Documentation technique</type>
    <description>Cet ouvrage explique les fondements du XML.
        <epoque>De nos jours</epoque>
        <resume>Résumé de l'ouvrage</resume>
    </description>
    <commentaire>Bon rapport qualité prix.</commentaire>
    <commentaire>Bonne explication des bases.</commentaire>
</livre>

Et obtenir un document valide.

23.2.6. Document formation

Soit une formation composée de sessions qui elles-même comportent des apprenants. Ces apprenants ont un nom et un prénom et peuvent faire partie de différents groupes. Nous considérons le document suivant:

<formation>
    <session nom="01-2006">
        <apprenants>
            <apprenant identifiant="jdupond" password="jean">
                <nom>dupond</nom>
                <prenom>jean</prenom>
                <groupes>reseau information</groupes>
            </apprenant>
            <apprenant identifiant="mdurant" password="marie">
                <nom>durant</nom>
                <prenom>marie</prenom>
                <groupes>information developpement</groupes>
            </apprenant>
            <apprenant identifiant="pdujardin" password="pierre">
                <nom>dujardin</nom>
                <prenom>pierre</prenom>
                <groupes>reseau information</groupes>
            </apprenant>
            <apprenant identifiant="elamarche" password="eric">
                <nom>lamarche</nom>
                <prenom>eric</prenom>
                <groupes>developpement sécurité/groupes>
            </apprenant>
        </apprenants>
    </session>
</formation>

Écrivez la DTD et le schéma XML de ce document, vous pourrez vous aider des fonctions de validations que nous avons vues. Pour compléter le schéma vous pourrez considérer qu´une session ne peut pas avoir moins de 3 apprenants et au maximum 10.

la DTD:

<!-- DTD d'un document formation -->

<!ELEMENT formation (session)>
<!ELEMENT session (apprenants)>
<!ATTLIST session nom CDATA #REQUIRED>
<!ELEMENT apprenants (apprenant+)>
<!ELEMENT apprenant (nom,prenom,groupes)>
<!ATTLIST apprenant identifiant CDATA #REQUIRED>
<!ATTLIST apprenant password CDATA #REQUIRED>
<!ELEMENT nom (#PCDATA)>
<!ELEMENT prenom (#PCDATA)>
<!ELEMENT groupes (#PCDATA)>

le schema

<?xml  version="1.0"  encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="formation" type="formationType"/>
<xsd:complexType name="formationType">
<xsd:sequence>
    <xsd:element name="session">
        <xsd:complexType >
            <xsd:sequence>
                <xsd:element name="apprenants">
                    <xsd:complexType >
                        <xsd:sequence>
                            <xsd:element name="apprenant" minOccurs="3"
                            maxOccurs="10">
                            <xsd:complexType mixed="true">
                                <xsd:sequence>
                                    <xsd:element name="nom" type="xsd:string"/>
                                    <xsd:element name="prenom" type="xsd:string"/>
                                    <xsd:element name="groupes" type="xsd:string"/>
                                </xsd:sequence>
                                <xsd:attribute name="identifiant" type="xsd:string"/>
                                <xsd:attribute name="password" type="xsd:string"/>
                            </xsd:complexType>
                            </xsd:element>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
            <xsd:attribute name="nom" type="xsd:string"/>
        </xsd:complexType>
    </xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

le php pour le test

<?php
$document = new DOMDocument;
$document->load("formation.xml");
 if($document->validate())
{
    echo $document->saveXML();
}
else{
    echo  "Le  document  n´est  pas  valide.";
}
if($document->schemaValidate("formation.xsd")) {
    echo "Le document est valide." ;
} else {
    echo "Le document n´est pas valide.";
}
?>