XML
xml

Cette page présente basiquement le langage de représentation de données XML et propose une application pratique de XML à la modélisation de questionnaires à choix multiples ou à choix unique, grâce à une feuille de style XML (XSL). Enfin, il se termine par un traitement de ces QCM par une page php pour la correction..

Sommaire :

  1. Présentation de XML
  2. Quelques règles
  3. Définition de la structure des données : DTD DataType Description
  4. Définition de la structure des données : Schéma XML
  5. Représentation des données : XSL, la feuille de style XML

Présentation de XML

XML, pour Extensible Markup Language, est littéralement un langage à balises extensible, comme HTML, mais pour lequel on peut définir ses propres balises et associer un sens au contenu de ces balises. Ce langage est donc très adapté à la représentation de données. Pour mieux comprendre de suite, voyons un exemple :

<recette>
    <titre>Moules Marinieres</titre>
    <ingredients>
        <ingredient><qty>50 cl</qty><ingnom>Vin Blanc</ingnom></ingredient>
        <ingredient><qty>1 kg</qty><ingnom>Moules fraiches</ingnom></ingredient>
        <ingredient><qty>3</qty><ingnom>Oignons</ingnom></ingredient>
    </ingredients>
    
    <preparation>
        <duree>15 min</duree>
        <cuisson>1 heure</cuisson>
        <explications>
        Nettoyer les moules à l'eau froide
        Emincer les oignons et les faire revenir
        ...
        </explications>
    </preparation>
</recette>

La représentation des données d'une recette est ici très claire car les balises donnent un sens à leur contenu. L'imbrication des balises est aussi logique car on comprend que tous les ingrédients de la recette, dans <ingredients>, sont une liste d'ingrédients simples, dans <ingredient>.

Quelques règles

Le langage XML est très strict, et la moindre erreur de syntaxe provoquera une erreur. Il faut donc veiller à respecter ces règles. Par exemple :

  1. Toujours fermer une balise : <balise> </balise> Une balise ouvrante seule provoquera une erreur
  2. Pour utiliser une balise sans la fermer, on écrit : <balise/>
  3. Ne pas enchevêtrer de balises : <balise><autre></balise></autre>
  4. Ne pas mettre de caractères accentués mais utiliser le code correspondant avec &#xxx;.
  5. Les codes &eacute; et associés ne sont pas compris par XML.
Définition de la structure de données : le DTD

Pour pouvoir faire une description de données, on doit se donner un modèle de représentation, qui décrit précisément de quoi se compose une recette, par exemple : quelles sont les informations obligatoires (les ingrédients, la préparation) et les informations facultatives (le vin qui accompagne bien la recette, le conseil du chef), etc. Pour cela, une méthode est d'utiliser un fichier .dtd (pour DataType Desxription) dans lequel on formalise tout ça :

<!ELEMENT recette ( titre, ingredients, preparation ) >
<!ELEMENT titre ( #PCDATA ) >
<!ELEMENT ingredients ( ingredient+ ) >
<!ELEMENT ingredient ( qty, ingnom ) >
<!ELEMENT qty ( #PCDATA ) >
<!ELEMENT ingnom ( #PCDATA ) >
<!ELEMENT preparation ( duree, cuisson, explication ) >
<!ELEMENT duree ( #PCDATA ) >
<!ELEMENT cuisson ( #PCDATA ) >
<!ELEMENT explication ( #PCDATA ) >

Cette modélisation met bien en évidence les imbrications possibles entre les balises (par exemple, une balise <qty></qty> sera toujours fille de <ingredient></ingredient>).

  1. La quatrième ligne dit par eemple qu'un ingrédient est la donnée s'une quantité et d'un nom d'ingrédient.
  2. La troisième ligne contient un caractère à une signification particulière : ici "+" signifie qu'un objet <ingredients/> se compose d'un ou plusieurs <ingredient/>.

Voici les autres caractères utiles pour des structures particulières :

symbole signification exemple
+ L'élément doit être présent au minimum une fois A+
* L'élément peut être présent plusieurs fois (ou aucune) A*
? L'élément peut être optionnellement présent A?
| L'élément A ou B peuvent être présents (pas les deux) A | B
, L'élément A doit être présent et suivi de l'élément B A, B
( ) Les parenthèses permettent de regrouper des éléments afin de leur appliquer les autres opérateurs (A | B)+

Attibuts : associé(s) à un élément particulier, ils permettent de lui attacher une paire "clé/valeur", où Type représente le type de données de l'attribut :

<! ATTLIST Elément Attribut Type >

Type de données :

  1. littéral : chaîne de caractères : avec le mot clé CDATA : <! ATTLIST Elément Attribut CDATA >
  2. l'énumération : liste de valeurs possibles : <! ATTLIST Elément Attribut (Valeur1 | Valeur2 | ... ) >
  3. l'énumération avec une valeur par défaut : <! ATTLIST Elément Attribut (Valeur1 | Valeur2 ) "valeur par défaut" >
  4. atomique : définir un identifiant unique pour chaque élément, une clé : grâce au mot clé ID.
<! ATTLIST disque IDdisk ID #REQUIRED>

Niveau de nécessité d'un attribut (optionnel) :

  1. #IMPLIED : attribut optionnel
  2. #REQUIRED : attribut est obligatoire
  3. #FIXED : attribut affecté d'une valeur par défaut s'il n'est pas défini. Doit être immédiatement suivi de la valeur entre guillemets
<! ATTLIST disque IDdisk ID #REQUIRED>

Lien entre une feuille XML et le DTD :

<?xml version="1.0"?>
<!DOCTYPE recette SYSTEM "qcm.dtd">
<recette>
   ...
</recette>

Définition de la structure de données : le Shéma XML

Plus récent et plus complexe, le schéma XML permet de faire des descriptions plus précises que le DTD. Voyons l'exemple de la recette modélisé par un schéma XML :

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://e-charle.fr/TNS" xmlns="http://e-charle.fr/TNS"
  elementFormDefault="qualified">
<xsd:element name="recette">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element ref="titre" minOccurs="1" maxOccurs="1"/>
            <xsd:element ref="ingredients" minOccurs="1" maxOccurs="1"/>
            <xsd:element ref="preparation" minOccurs="1" maxOccurs="1"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>

<xsd:element name="titre" type="xsd:string"/>

<xsd:element name= "ingredients">
    <xsd:complexType>
        <xsd:sequence>
        <xsd:element ref="ingredient" minOccurs="0" maxOccurrs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>

<xsd:element name= "ingredient">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element ref="qty" minOccurs="0" maxOccurrs="unbounded"/>
            <xsd:element ref="ingnom" minOccurs="0" maxOccurrs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>

<xsd:element name="qty" type="xsd:string"/>
<xsd:element name="nom" type="xsd:string"/>

<xsd:element name= "preparation">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element ref="duree" minOccurs="1" maxOccurrs="1"/>
            <xsd:element ref="cuisson" minOccurs="1" maxOccurrs="1"/>
            <xsd:element ref="explcation" minOccurs="1" maxOccurrs="1"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>

<xsd:element name="duree" type="xsd:string"/>
<xsd:element name="cuisson" type="xsd:string"/>
<xsd:element name="explication" type="xsd:string"/>

Présentation des données XML : XSLT

Le fichier XSLT est une feuille de style XMl qui permet de définir la manière de représenter les informations contenues dans le fichier XML : quelles sont les informations doivent apparaître, comment les mettre en forme (listes, tableaux), quelles polices et couleurs utiliser pour les afficher dans le navigateur. Voici le squelette d'une feuille de style XSLT :

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"
  xmlns="http://www.w3.org/TR/REC-html40" result-ns="">
    <xsl:template ... >
        <!-- traitements à effectuer -->
    </xsl:template >
</xsl:stylesheet>

En général, dans les traitements à effectuer, on met des balises HTML correspondant à celles d'une page web standerd : <html><head><body>, etc. Il faut toujours se rappeler qu'on doit ici refermer obligatoirement une balise ouverte (ex : <br> </br>) ou l'écrire particulièrement (<br/>). Voici un exemple de fichier XSLT correspondant à un fichier XML représentant un qcm.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="recette">
    <html>
      <head>
        <title>QCM</title>
        <link href="qcm.css" rel="stylesheet" type="text/css"/>
      </head>
      <body bgcolor="#ffffff">
        <div class="titre">Recette</div>
        <xsl:apply-templates/>
      </body>
      </html>
  </xsl:template>

  <xsl:template match="titre"></xsl:template>

  <xsl:template match="ingredients">
    <ul>Les ingredients :</ul>
    <ol><xsl:copy><xsl:apply-templates /></xsl:copy></ol>
  </xsl:template>

  <xsl:template match="ingredient">
    <li><b><xsl:value-of select="qty"/></b> - <xsl:value-of select="ingnom"/></li>
  </xsl:template>

  <xsl:template match="preparation">
    <p><u>Duree :</u> <xsl:value-of select="duree"/></p>
    <p>
      <u>Explication :</u><br>
      <xsl:value-of select="explication"/>
    </p>
  </xsl:template>

  <xsl:template match="duree"></xsl:template>
  <xsl:template match="explication"></xsl:template>
</xsl:stylesheet>

Quelques explications :

  1. La description d'un élément est déclarée entre des balises <xsl:template> </xsl:template>, la propritété match permet de dire à quoi la description fait référence.
     
  2. J'ai mis ici la structures de balises d'une page web dans la description de la représentation de l'élément principal de la feuille : la recette.
     
  3. On peut utiliser la balise <xsl:value-of select="..."/> pour faire référence à un enfant de l'objet pour lequel on fait le template afin de récupérer son contenu. J'ai utilisé cette méthode pour la représentation de la préparation. Notez alors que dans ce cas, il faut que je spécifie que je ne veux pas en plus représenter les données "durée" et "explication" sinon je les aurais en double. Donc j'ai aussi fait : <xsl:template match="duree"></xsl:template> <xsl:template match="explication"></xsl:template>.
     
  4. Pour aller plus loin, il est possible d'associer une feuille de style CSS à la page web que l'on veut générer. Il suffit de placer la balise y faisant référence dans le code de la page html décrit dans le template de l'objet recette : <link href="recette.css" rel="stylesheet" type="text/css"/>.

Techniques avancées :

Les XPath permettent d'accéder à des propriétés de descendants ou de parents d'un objet, de récupérer des attributs caractéristiques d'un objet. J'en ai par exemple utilisé dans le cas de la préparation. Il y a quelques caractères spéciaux qui permettent de bien utiliser cette possibilité :

symbole exemple signification
| "Gauche|Milieu" Indique une alternative (un noeud ou bien l'autre (ou les deux))
/ "personne/nom" Chemin d'accès aux éléments (personne/bras/gauche) comme une arborescence
* "*" Motif "joker" désignant n'importe quel élément
// "//personne" Désigne tous les descendants d'un noeud
. "." Désigne le noeud courant
.. ".." Désigne le noeud parent
@ "@valeur" Désigne un attribut caractéristique (dans l'exemple l'attribut value)

Modification d'un attribut d'une balise encadrant notre code : En fonction des données que nous représentons, il se peut que l'on veuille modifier l'aspect de la représentation des données en changeant l'attribut d'une balise qui encadre. Par exemple si l'on veut représenter tous les enfants d'une famille nombreuse dans un tableau, on pourrait vouloir mettre le fond des cellules des filles en rose et celui des garçons en bleu. Associé à une feuille de style, cette méthode est très puissante. Exemple dans notre cas :

<td><xsl:attribute name="class"><xsl:value-of select="./sexe"/></xsl:attribute><xsl:value-of select="./prenom"/></td>

Il suffit alors de définir une classe "m" et une classe "f" pour la représentation des td dans une feuille de style CSS pour avoir le résultat escompté :

.m {
 border-style:solid; 
 border-width:1px; 
 border-color: #e0edfa; 
 background-color: #e0edfa;
}
.f {
 border-style:solid; 
 border-width:1px; 
 border-color: #ffe8f7; 
 background-color:#ffe8f7;
}
enfants
Paul
Emilie
Marc
Jacques
Sophie