Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
Le minimum à savoir sur XML : intérêts, notion de document bien formé, technologies liées, etc.
GÉNÉRALITÉS
XML n'est pas un langage à proprement parler comme peut l'être HTML : XML est une famille de langages ayant en commun le respect de
certaines règles. Nous allons voir que là où HTML est simple, bien défini et non contraignant à la fois, XML est extensible et rigoureux.
En pratique, un fichier XML est un simple fichier texte, contenant des balises. La particularité de XML est qu'aucune balise n'est prédéfinie :
c'est au concepteur de définir les balises qui ont du sens pour lui.
Ces éléments permettent d'ores et déjà de dégager les intérêts de XML :
• Les documents sont faciles à compléter ou à modifier, il suffit d'un simple éditeur de texte parce qu'il s'agit de fichiers texte avec
un format connu et simple ;
• l'aspect textuel autorise également des recherches de base, soit à travers l'éditeur de texte, soit à l'aide des commandes de base
du système d'exploitation (grep sous Linux) ;
• comme il s'agit d'un format ouvert, des outils génériques sont disponibles et directement utilisable, du parser (lecture et
chargement du fichier en mémoire) à la transformation automatique avec XSLT ;
• l'utilisateur peut différencier le fond de la forme, ne travailler que sur la structure logique du document sans se soucier de sa
présentation ; cela car XML est clairement avant tout une solution de stockage et pas de publication.
Sur l'aspect stockage et recherche, le langage XML semble s'opposer aux bases de données. On l'a vu XML permet la saisie et les
modifications sans autre logiciel qu'un traitement de texte. Même une modification du schéma est facile à gérer en XML, au moins sur un
unique document XML. De plus, XML ne nécessite pas dans un premier temps l'apprentissage d'un langage comme SQL. Cependant,
l'efficacité des recherches reste l'avantage des bases de données.
XML est donc un standard ouvert et universel. On le trouve aujourd'hui dans les domaines les plus variés :
• édition (description d'ouvrage avec DocBook),
• graphisme (format SVG),
• mathématiques (formules avec MathML),
• chimie (CML permet la description de molécules en 3D),
• musique (partition musicale avec MusicML),
• etc.
• la première ligne doit être de la forme <?xml version="1.0" encoding="iso-8859-1" ?> ; les deux attributs spécifient la version de
XML utilisée (1.0 ou 1.1) et le codage des caractères (utf-8 par défaut) ;
• les balises sont repérées par les caractères < et >, on écrira par exemple <balise>contenu</balise> ; la balise ouvrante peut
contenir des attributs ;
• toujours donner une valeur aux attributs, en suivant la syntaxe <balise attr="val"> (les guillemets sont obligatoires, les attributs ne
sont pas répétés dans la balise fermante) ;
• les entités sont systématiquement de la forme &nom; ;
• fermer toutes les balises ouvertes ; une balise sans contenu pourra être ouverte et immédiatement fermée en faisant suivre son
nom d'un slash, par exemple avec la balise br (passage à la ligne en HTML) : <br /> ;
• veiller à l'ordre de fermeture des balises : la première ouverte est toujours la dernière fermée ;
• respecter la casse : on peut utiliser majuscules et minuscules dans les noms de balises mais une fois qu'un nom d'élément a été
fixé, il faut s'y tenir, la balise <cv> ne pourra être fermée ni par </Cv> ni par </CV> ;
• ne pas utiliser de caractères réservés à XML dans le texte du document : <, > et & ; ces caractères pourront être respectivement
obtenues à l'aide des entités <, > et & ;
• les noms de balises et d'attributs doivent être des noms XML :
• le premier caractère est une lettre quelconque ou un _ (underscore ou tiret bas) ;
• les caractères suivants peuvent être des lettres, des chiffres, des tirets bas (_), des traits d'union (-) ou des points (.) ;
• il n'y a pas de limitation sur la longueur d'un nom XML.
à noter que cette dernière règle interdit à un nom de balise de commencer par un chiffre. Cependant, la liberté pour choisir un nom
d'élément reste grande car on peut y faire figurer n'importe quelle lettre... or, le codage privilégié dans les documents et applications XML
est l'UTF-8 qui contient les alphabets latin, arabe, japonais, etc. Plus spécifiquement, on n'hésitera pas à utiliser des lettres accentuées
dans les noms d'éléments.
Finalement, voici un exemple de document XML bien formé :
<?xml version="1.0" encoding="iso-8859-1" ?>
<!-- commentaire : voici mon curriculum vitae -->
<cv>
<!-- commentaire : état civil -->
<identité naissance="1980">
<nom>Moustique</nom>
<prénom>Jules</prénom>
<prénom>Édouard</prénom>
<nationalité>grolandaise</nationalité>
</identité>
<!-- commentaire : mes diplômes maintenant -->
<diplome année="2005" intitulé="Master ID" mention="TB" />
<diplome année="2003" intitulé="Licence " mention="AB" />
</cv>
TECHNOLOGIES LIÉES
La simplicité et l'ouverture de XML fait qu'un document XML peut facilement être modifier par un être humain, sans outil spécifique.
La rigueur de XML (sensibilité à la casse, guillemets obligatoires pour encadrer les valeurs des attributs, fermeture systématique des
balises, etc.) autorise des traitements automatiques, qui pourront être partagés par tous les langages XML.
• contraindre un langage XML : DTD, Schémas, Relax NG ;
• mise en page avec CSS
MOTIVATIONS
Nous avons vu comment il était possible d'écrire du XML en respectant ses règles de syntaxe et d'obtenir ainsi un document XML bien
formé.
Nous allons maintenant décrire comment spécifier des contraintes plus précises et propres à notre langage XML. Cela va prendre ici la
forme d'une DTD (Définition de Type de Document).
On dira alors qu'en plus d'être bien formé, le document est valide par rapport à une certaine DTD.
Cette spécification d'une grammaire pour un langage et la possibilité de tester automatiquement son respect par un document donné,
présentent les avantages suivants :
• faciliter l'échange et la mise en commun de documents produits par des rédacteurs différents ;
• aider les développeurs qui conçoivent des outils automatiques pour traiter les documents respectant la même DTD.
DTD INTERNE
Dans ce cas, la spécification de la DTD arrive dans l'entête du document XML : on trouve d'abord le mot-clef DOCTYPE suivi de l'élément
servant de racine au document et enfin la DTD elle-même entre crochets :
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE cv [
.
.
.
]>
<cv>
.
.
.
</cv>
DTD EXTERNE
Cette fois, la DTD est détachée dans un fichier séparé, on se contente d'y faire référence dans l'entête du document XML. On retrouve le
mot-clef DOCTYPE suivi de l'élément servant de racine, puis le mot-clef SYSTEM suivi d'une URI menant au fichier DTD.
À noter également que la première ligne doit faire apparaître l'attribut standalone avec la valeur no.
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE cv SYSTEM "cv.dtd">
<cv>
.
.
.
</cv>
À noter que, sans toucher au document XML, il est possible de faire le lien au moment de la validation. Par exemple, avec xmllint, on écrira :
xmllint --dtdvalid madtd.dtd mondoc.xml --noout
DTD MIXTE
Enfin, il est possible de mélanger les deux notations pour avoir une partie de la DTD dans un fichier séparé et une autre partie embarquée
dans le document XML :
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE cv SYSTEM "cv.dtd" [
.
.
.
]>
<cv>
.
.
.
</cv>
DÉFINIR LES ÉLÉMENTS ET LEURS CONTENUS
Il s'agit ici de déclarer les éléments autorisés à apparaître dans le document, ainsi que leurs imbrications possibles. La forme générale est la
suivante :
<!ELEMENT nom_element modèle_de_contenu>
Les noms des éléments (comme ceux des attributs) doivent être des noms XML :
Aucune balise n'est donc tolérée dans ce type de contenu mais, par contre, il est possible d'y utiliser des entités.
SOUS-ÉLÉMENTS
Ici, on va lister les sous-éléments pouvant apparaître dans le contenu, par exemple :
<!ELEMENT identité (prénom,nom)>
indique que l'élément identité doit contenir, dans l'ordre, un élément prénom, un élément nom, et rien d'autre.
Il est possible de moduler le nombre d'apparitions d'un sous-élément en utilisant des quantifieurs après les noms d'éléments. Les
quantifieurs utilisables dans les DTD sont :
• ? : 0 ou 1 fois ;
• * : 0, 1 ou plus ;
• + : 1 ou plus.
L'exemple suivant indique que l'élément identité doit contenir, toujours en respectant l'ordre, un ou plusieurs éléments prénom, un
élément surnom facultatif et exactement un élément nom :
<!ELEMENT identité (prénom+,surnom?,nom)>
ALTERNATIVES
Il est également possible de définir les sous-éléments qui peuvent apparaître de manière exclusive : si c'est l'un, ça n'est pas les autres.
Dans l'exemple ci-dessous, une expérience professionnelle peut être soit un emploi, soit un stage :
<!ELEMENT expérience (stage|emploi)>
COMBINAISONS
Enfin, il est possible de combiner les syntaxes vues précédemment :
<!ELEMENT diplôme ( (intitulé,année) | (année,compétences,stage?)+ )>
CONTENU MIXTE
Une possibilité intéressante est de pouvoir mixer du texte brut avec des balises sans mettre plus de contraintes sur l'ordre et le nombre
d'apparitions de ces balises. Cela se fait avec une alternative entre un contenu de type PCDATA et des sous-éléments, cette alternative
pouvant se répéter plusieurs fois :
<!ELEMENT parcours (#PCDATA | diplôme)*>
Ici, on a un élément parcours qui a un contenu mixte : du texte pouvant contenir un nombre quelconque de sous-éléments diplôme.
CONTENU VIDE
Un élément peut également n'avoir aucun contenu, comme c'est le cas par exemple de la balise br (retour à la ligne en HTML). Cela se
précise dans la DTD de la manière suivante :
<!ELEMENT br EMPTY>
Une telle balise sera donc ouverte et immédiatement refermée avec la notation suivante : <br />.
CONTENU QUELCONQUE
On termine avec la possibilité d'autoriser n'importe quel contenu à apparaître dans un élément.
<!ELEMENT mavie ANY>
Dans ce cas, l'élément mavie pourra contenir du texte brut mélangé avec toute balise définie dans la DTD, dans n'importe quel ordre, autant
de fois que l'on veut.
Ce modèle de contenu est en contradiction avec l'esprit des DTD, lesquelles visent plutôt à restreindre au maximum le rédacteur. Une
utilisation cependant pratique du ANY intervient lors de la rédaction d'une DTD alors que les documents XML sont déjà existants : dans ce
cas, on définit les éléments de plus haut niveau en indiquant ANY pour leurs contenus, si les documents sont valides, on reprend la DTD en
affinant le contenu de chacun des éléments, etc.
Dans ce cas, l'élément identité possède trois attributs prénom, nom et surnom. Les deux premiers sont obligatoires (REQUIRED) et le
dernier est optionnel (IMPLIED). À noter également la possibilité pour un attribut d'être FIXED, c'est-à-dire de prendre systématiquement la
même valeur.
Nous passons maintenant en revue les différents types d'attributs.
CDATA
Type général qui permet de saisir un texte quelconque pour un attribut de ce type.
NMTOKEN
Il s'agit ici un nom XML mais sans restriction sur le premier caractère (qui peut donc être un chiffre). Une contrainte essentielle est donc
qu'un attribut de ce type ne contiendra pas d'espace.
Par exemple, un code postal pourra être déclaré de ce type :
<!ATTLIST ville nom CDATA #REQUIRED
code NMTOKEN #REQUIRED>
NMTOKENS
Une suite de NMTOKEN, séparés par des espaces.
ÉNUMÉRATION
Dans ce cas, l'attribut ne peut prendre qu'un nombre fini de valeurs et l'on en donne la liste exhaustive, ces valeurs étant séparées par des |.
<!ATTLIST date jour (lundi|mardi|mercredi|jeudi|vendredi|samedi|dimanche) #REQUIRED
num NMTOKEN #REQUIRED
mois NMTOKEN #REQUIRED
année NMTOKEN #REQUIRED>
ID
Il doit s'agir d'un nom XML qui identifie de manière unique l'élément. Autrement dit, une valeur qui apparaît dans un tel attribut ne peut pas
apparaître une seconde fois dans le même document.
<!ATTLIST diplôme intitulé CDATA #REQUIRED
code ID #REQUIRED>
Cette notion est tout à fait comparable à la clef primaire d'une table dans une base de données. Cependant, il faut garder à l'esprit
qu'un ID ne peut pas être un nombre (car la valeur d'un ID doit être un nom XML).
IDREF
Un attribut de type IDREF doit contenir une valeur utilisée comme ID ailleurs dans le document.
<!ATTLIST stage entreprise CDATA #REQUIRED
diplôme IDREF #REQUIRED>
IDREFS
Une suite de IDREF, séparées par des espaces.
ENTITY
La valeur d'un attribut de ce type doit être une entité définie dans la DTD (voir section suivante pour la définition des entités).
ENTITIES
Une suite de ENTITY, séparées par des espaces.
ENTITÉS GÉNÉRALES
Le mot ENTITY suivi du nom de l'entité, puis de sa valeur entre guillemets ou apostrophes.
<!ENTITY ac "anticonstitutionnellement">
Cette déclaration permettra d'utiliser ∾ dans le document XML associé à la DTD.
La valeur de l'entité peut contenir du texte, des balises et des entités (le code XML ainsi défini doit être bien formé). Par exemple,
<!ENTITY piedpage '<hr />
<p>
Copyright 2005, dernière mise à jour octobre 2005.
</p>'>
ENTITÉS GÉNÉRALES EXTERNES
Si le code associé à une entité devient très important, il peut être intéressant de le détacher dans un fichier à part, ce que permet la syntaxe
suivante :
<!ENTITY piedpage SYSTEM "pp.xml">
Dans ce cas, le fichier pp.xml doit être un fichier XML bien formé (première ligne de déclaration de la version XML et du codage utilisé,
fermeture systématique des balises ouvertes, etc.).
Ici, en plus du fichier externe, on trouve NDATA pour Notation Data et jpeg faisant référence à une NOTATION définie précédemment.
La NOTATION doit permettre à l'application de traiter le fichier externe : il peut s'agir d'un type MIME comme ici ou d'une commande à
exécuter.
Une telle entité pourra apparaître comme valeur d'un attribut défini avec le type ENTITY.
on charge la dtd avec --valid et on demande la substitution des entités avec --noent.
ENTITÉS PARAMÈTRES
Ce type d'entité permet d'éviter de répéter les mêmes informations. Par exemple, on donnera toujours le nom et le prénom d'une personne,
quel que soit son statut dans le document :
<!ELEMENT identité (nom,prénom,naissance)>
<!ELEMENT enseignant (nom,prénom)>
L'utilisation d'une entité paramètre comme suit permet de ne pas répéter et autorise à enrichir ultérieurement la description d'une personne :
<!ENTITY % elements_personne "nom,prénom">
<!ELEMENT identité (%elements_personne;,naissance)>
<!ELEMENT enseignant (%elements_personne)>
DTD MODULAIRES
Des instructions (INCLUDE et IGNORE) permettent de prendre en compte un bloc de la DTD, ou de l'ignorer. La syntaxe est la suivante :
<![IGNORE[
<!ELEMENT personne (nom,prénom)>
<!ELEMENT nom (#PCDATA)>
<!ELEMENT prénom (#PCDATA)>
]]>
<![INCLUDE[
<!ELEMENT entreprise (dénomination,taille)>
<!ELEMENT dénomination (#PCDATA)>
<!ELEMENT taille (#PCDATA)>
]]>
Comment définir un XML Schéma : types, modèles de contenu, éléments et imbrication, attributs, etc.
LA BASE PRATIQUE
Le fichier XML :
<racine
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="monschema.xsd">
.
.
.
</racine>
<xs:simpleType name="motdepasse">
<xs:restriction base="xs:string">
<xs:minLength value="8" />
<xs:maxLength value="20" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="telephone">
<xs:restriction base="xs:string">
<xs:length value="10" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="prix">
<xs:restriction base="xs:decimal">
<xs:fractionDigits value="2" />
</xs:restriction>
</xs:simpleType>
DÉFINIR UN ATTRIBUT
Finalement :
<xs:element name="nom" minOccurs="1" maxOccurs="1" type="xs:string" />
<xs:element name="prénom" minOccurs="1" maxOccurs="unbounded" type="xs:string" />
<xs:element name="surnom" minOccurs="0" maxOccurs="1" type="xs:string" />
<xs:element name="br">
<xs:complexType>
<xs:attribute name="class" type="string" />
</xs:complexType>
</xs:element>
Il s'agit à nouveau d'utiliser <xs:complexType> puis de lister les sous-éléments autorisés au sein de l'une de ces balises :
<xs:element name="auteur">
<xs:complexType>
<xs:sequence>
<xs:element name="nom" minOccurs="1" maxOccurs="1" type="xs:string" />
<xs:element name="prénom" minOccurs="1" maxOccurs="unbounded" type="xs:string" />
<xs:element name="surnom" minOccurs="0" maxOccurs="1" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
CONTENU MIXTE
On définit pour cela un type complexe en précisant un attribut mixed, celui-ci indiquant que du texte peu se glisser entre tous les sous-
éléments autorisés.
<xs:element name="p">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="em" type="xs:string" />
<xs:element name="strong" type="xs:string" />
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="CHAMPIONNAT">
<xs:complexType>
<xs:sequence>
<xs:element name="JOURNEE" maxOccurs="38">
<xs:complexType>
<xs:sequence>
<xs:element name="RENCONTRE" maxOccurs="10">
<xs:complexType>
<xs:attribute name="DOMICILE" type="xs:string" />
<xs:attribute name="EXTERIEUR" type="xs:string" />
<xs:attribute name="SCORED" type="xs:string" />
<xs:attribute name="SCOREE" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="NUMERO" type="xs:integer" />
<xs:attribute name="DATE" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="DIVISION" type="xs:integer" />
<xs:attribute name="SAISON" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:schema>
<xs:element name="RENCONTRE">
<xs:complexType>
<xs:attribute ref="DOMICILE" />
<xs:attribute ref="EXTERIEUR" />
<xs:attribute ref="SCORED" />
<xs:attribute ref="SCOREE" />
</xs:complexType>
</xs:element>
<xs:element name="JOURNEE">
<xs:complexType>
<xs:sequence>
<xs:element ref="RENCONTRE" maxOccurs="10" />
</xs:sequence>
<xs:attribute ref="NUMERO" />
<xs:attribute ref="DATE" />
</xs:complexType>
</xs:element>
<xs:element name="CHAMPIONNAT">
<xs:complexType>
<xs:sequence>
<xs:element ref="JOURNEE" maxOccurs="38" />
</xs:sequence>
<xs:attribute ref="DIVISION" />
<xs:attribute ref="SAISON" />
</xs:complexType>
</xs:element>
</xs:schema>
La première stratégie contraint l'élément racine, pas la seconde. La seconde est plus modulaire et permet de réutiliser des parties du
schéma.
UNICITÉ
<xs:element name="bibliotheque">
<xs:complexType>
...
</xs:complexType>
<xs:unique name="uniquelivre">
<xs:selector xpath="book" />
<xs:field xpath="isbn" />
</xs:unique>
</xs:element>
CLÉS
<xs:element name="bibliotheque">
<xs:complexType>
...
</xs:complexType>
<xs:key name="cleflivre">
<xs:selector xpath="livre" />
<xs:field xpath="isbn" />
</xs:key>
</xs:element>
RÉFÉRENCE
<xs:keyref name="refcleflivre" refer="cleflivre">
<xs:selector xpath="citation"/>
<xs:field xpath="ref" />
</xs:keyref>
REGROUPEMENTS
<xs:element name="identite">
<xs:complexType>
<xs:attributeGroup ref="attrs_photo" />
<xs:attribute name="personne" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="paysage">
<xs:complexType>
<xs:attributeGroup ref="attrs_photo" />
<xs:attribute name="lieu" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="p">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:group ref="elems_text" />
</xs:choice>
</xs:complexType>
</xs:element>
Les transformations XSLT
Présentation de XSLT, langage de transformation pour les documents XML.
MOTIVATIONS ET GÉNÉRALITÉS
XSLT est un langage central dans le monde XML et beaucoup de qualités reconnues de XML reposent en fait sur l'utilisation de XSLT :
productions de versions diffusables (HTML, PDF, etc.), pérennité des documents, ouverture des formats, interopérabilité, etc.
La première motivation est d'associer un style à un document XML, tout comme on associe une feuille de style CSS à une page HTML. Les
CSS sont utilisables avec les documents XML mais présentent plusieurs défauts :
• les CSS ne permettent pas d'extraire les valeurs des attributs pour les faire apparaître ;
• il est possible avec les CSS de placer les blocs les uns par rapport aux autres, d'en faire disparaître certains, mais pas de tout
réorganiser de fond en comble, encore moins de créer de nouvelles données ;
• le langage CSS n'est pas un langage XML.
Cela amène à la définition d'un nouveau format : XSL pour eXtensible Stylesheet Language. Cependant, les critiques des CSS ont fait
apparaître deux besoins bien différents : mettre en page le document XML et, par ailleurs, lui faire subir des transformations. D'où la
définition de deux langages XML : XSL-FO (XSL Formating Objects) et XSLT (XSL Transformations). Dans ce cours, on ne s'intéresse qu'à
la partie XSLT.
Une transformation XSLT est donc d'abord un fichier XML, auquel on donne en général l'extension .xsl et qui au minimum contient :
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
.
... ici des règles de transformation ...
.
</xsl:stylesheet>
De manière générale, XSLT permet de transformer un document XML en un autre document XML. Parmi les formats utilisés comme sortie
de XSLT citons : FO, XHTML, SVG, DocBook, etc.
Pour appliquer une feuille de transformation XSLT à un document XML, une première solution consiste à introduire un lien dans la
transformation dans le document :
<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="doc2html.xsl" ?>
<document>
.
.
.
</document>
Ainsi, les programmes traitant le document et disposant d'un processeur XSLT pourront choisir d'appliquer la transformation, c'est le cas par
exemple des navigateurs. Une autre solution est d'indiquer explicitement la feuille XSLT à appliquer au moment de la transformation, par
exemple avec xsltproc :
xsltproc doc2html.xsl doc.xml > doc.html
Terminons avec OpenOffice qui est lui aussi capable d'appliquer des transformations XSLT pour charger des documents dans un format
XML quelconque.
L'INSTRUCTION VALUE-OF
Dans sa forme la plus simple et la plus utilisée, l'élément value-of est associé à son attribut select qui lui contient une requête XPath
désignant une valeur (le contenu d'en élément textuel, d'un attribut ou encore le résultat d'un calcul). En voici quelques exemples :
<xsl:value-of select="nom" />
<xsl:value-of select="@date" />
<xsl:value-of select="/personnes/personne[@id='p12']/nom" />
<xsl:value-of select="." />
<xsl:value-of select="count(/personnes/personne)" />
<xsl:value-of select="position()" />
L'instruction value-of possède un autre attribut disable-output-escaping qui peut prendre deux valeurs yes ou no. Vaut no par défaut
indiquant que les caractères comme < ou > doivent être remplacés par leurs entités : respectivement < et >. On le met donc à yes pour
contraindre la sortie de ces caractères sans modification.
L'appel à linstruction value-of provoque la sortie de la valeur calculée dans le document final.
LES VARIABLES
Un autre besoin est de récupérer une valeur ou des noeuds et simplement de les stocker avant de les traiter. Pour cela, on définit une
variable comme dans un langage de programmation quelconque, ici avec un élément noté xsl:variable, un attribut name pour nommer la
variable et, à nouveau, un attribut select contenant une requête XPath.
<xsl:variable name="nomdefamille" select="nom" />
<xsl:variable name="ladate" select="@date" />
<xsl:variable name="nbpersonne" select="count(/personnes/personne)" />
<xsl:variable name="lapersonne" select="/personnes/personne[@id='p12']" />
<xsl:variable name="lesgens" select="/personnes/personne" />
Une fois la variable définie, on peut l'utiliser (typiquement dans une nouvelle requête XPath) en utilisant son nom avec le signe dollar devant
:
<xsl:variable name="refpersonne" select="citation/@ref" />
<xsl:value-of select="/personnes/personne[@id=$refpersonne]/nom" />
XSLT est un langage de programmation fonctionnel et par conséquent les variables ne sont pas modifiables. Il est donc déraisonnable
d'écrire quelque chose comme :
<xsl:variable name="i" select="$i+1" />
COPY ET COPY-OF
L'instruction copy-of reproduit un ensemble de noeuds récupéré par un select, avec la sous-arborescence de chacun. L'instruction copy elle
ne recopie que le noeud courant lui-même, sans son contenu et sans ses fils (il va donc falloir définir le nouveau contenu et les nouveaux
descendants).
Des exemples plus précis seront fournis dans les prochaines sections.
<xsl:template match="mesdiplomes">
. . .
</xsl:template>
Lorsque l'on décrit une règle de transformation, il faut garder à l'esprit que les requêtes XPath sont évaluées par rapport aux noeud courant.
Dans l'exemple suivant, nom et @année sont respectivement un sous élément et un attribut du diplôme que l'on est en train de transformer.
<xsl:template match="diplome">
<h2>
<xsl:value-of select="nom" />
</h2>
<p>
Obtenu en <xsl:value-of select="@année" />
</p>
</xsl:template>
Enfin, les appels se font à l'aide de l'instruction apply-templates et d'un attribut select contenant une requête XPath : celle-ci sélectionne des
noeuds pour lesquels on va chercher des règles de transformation à activer. Ci dessous, une feuille XSLT complète, qui commence par
traiter la racine.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="mesdiplomes" />
</body>
</html>
</xsl:template>
<xsl:template match="mesdiplomes">
<h1>Mon cursus</h1>
<xsl:apply-templates select="diplome" />
</xsl:template>
<xsl:template match="diplome">
<h2>
<xsl:value-of select="nom" />
</h2>
<p>
Obtenu en <xsl:value-of select="@année" />
</p>
</xsl:template>
</xsl:stylesheet>
Précisons que l'attribut select de apply-templates n'est pas obligatoire, il peut être omis. Dans ce cas, on va chercher à appliquer les règles
de transformation à chacun des noeuds fils (ce qui revient à poser select="node()" par défaut). Cela est particulièrement intéressant dans le
cas d'un contenu mixte :
<xsl:template match="paragraph">
<p>
<xsl:apply-templates />
</p>
</xsl:template>
<xsl:template match="important">
<em><xsl:value-of select="." /></em>
</xsl:template>
Lors de la transformation d'un paragraphe, les noeuds texte seront recopiés à l'identique, tandis que les éléments important seront traités
par la seconde règle.
Terminons avec des utilisations des instructions copy-of et copy. L'exemple suivant remplace les éléments paragraph en éléments p tandis
que le contenu, probablement mixte (texte et balises), est recopié à l'identique :
<xsl:template match="paragraph">
<p>
<xsl:copy-of select="*" />
</p>
</xsl:template>
La règle ci-dessous permet de récupérer l'ensemble d'un document XML en ajoutant un attribut à chacune des balises ouvertes :
<xsl:template match="*|/">
<xsl:copy>
<xsl:attribute name="lang">fr</xsl:attribute>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
LES MODES
Pour pouvoir traiter plusieurs fois mais de manière différente les mêmes éléments, il est possible de spécifier un mode, dans la règle de
transformation et dans son appel.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>Mon cursus</h1>
<ul>
<xsl:apply-templates select="diplome" mode="sommaire" />
</ul>
<xsl:apply-templates select="diplome" mode="tout" />
</body>
</html>
</xsl:template>
</xsl:stylesheet>
<a href="{lien/@url}">
<xsl:value-of select="lien/texte" />
</a>
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="lien/@url" />
</xsl:attribute>
<xsl:value-of select="lien/texte" />
</xsl:element>
<xsl:template match="text()|@*">
<xsl:value-of select="." />
</xsl:template>
<xsl:template select="...">
.
.
.
<xsl:call-template name="signature" />
.
.
.
</xsl:template>
On voit ici clairement le parallèle avec les procédures et fonctions des autres langages de programmation et l'étape suivante est
naturellement de munir les règles de transformation de paramètres. Cela se fait avec xsl:param pour la déclaration des paramètres dans la
règle et xsl:with-param pour leur instanciation au moment de l'appel :
<xsl:template name="faireunlien">
<xsl:param name="url" />
<xsl:param name="texte" />
<a href="{$url}">
<xsl:value-of select="$texte" />
</a>
</xsl:template>
Naturellement, la récursivité est encore plus explicite avec une règle nommée.
<xsl:template name="ancêtres">
<xsl:param name="noeud" />
<xsl:if test="name($noeud)='domaine'">
<xsl:call-template name="ancêtres">
<xsl:with-param name="noeud" select="$noeud/parent::*" />
</xsl:call-template>
<li><a href="{$noeud/@id}.html"><xsl:value-of select="$noeud/@intitulé" /></a></li>
</xsl:if>
</xsl:template>
Dans la cas suivant, on récupère un ensemble de noeuds et on vérifie qu'il est non vide avant de le traiter :
<xsl:choose>
<xsl:when test="starts-with(@href,'#')">
<a href="@href">lien interne</a>
</xsl:when>
<xsl:when test="starts-with(@href,'mailto:')">
<a href="@href">adresse mail</a>
</xsl:when>
<xsl:otherwise>
<a href="{@href}">lien web</a>
</xsl:otherwise>
</xsl:choose>
LA BOUCLE FOR-EACH
On a vu que les itérations étaient assurées par le mécanisme d'activation des règles. Celui-ci est suffisant et apparente XSLT à la famille
des langages fonctionnels. On trouve cependant en XSLT une boucle classique des langages impératifs :
<xsl:for-each select="mesdiplomes/diplome">
<h2>
<xsl:value-of select="nom" />
</h2>
<p>
Obtenu en <xsl:value-of select="@année" />
</p>
</xsl:for-each>
AUTRES POSSIBILITÉS DE XSLT
<xsl:template match="/">
<html>
<body>
<h1>Mon cursus</h1>
<xsl:for-each select="diplome">
<xsl:sort select="@année" order="descending" />
<h2><xsl:value-of select="nom" /></h2>
<p>Obtenu en <xsl:value-of select="@année" /></p>
</xsl:for-each>
</body>
</html>
</xsl:template>
PARAMÈTRES EXTERNES
On a parfois envie de passer des paramètres à la feuille XSLT pour conditionner la sortie, par exemple pour produire des documents
différents à partir du même document d'origine. Pour cela, on déclare les paramètres comme pour des templates paramétrés, sauf que
ceux-ci sont des fils directs de l'élément xsl:stylesheet :
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="cible" />
<xsl:param name="refpersonne" />
.
... ici des règles de transformation ...
.
Il reste à préciser les valeurs de ces paramètres au moment de la transformation. Avec xsltproc, cela se fait comme suit :
xsltproc --stringparam cible index doc2html.xsl doc.xml > index.html
xsltproc --stringparam cible unepersonne --stringparam refpersonne p12 doc2html.xsl doc.xml > doc.html
CONDITIONNER LA SORTIE
L'instruction xsl:output peut apparaître comme fils direct de l'élément xsl:stylesheet et permet de préciser la sortie voulue, en particulier à
travers les attributs suivants :
PRODUIRE DU TEXTE
Par exemple pour contraindre deux valeurs extraites à être séparées par un espace :
<xsl:value-of select="$prénom" />
<xsl:text> </xsl:text>
<xsl:value-of select="$nom" />
Cours sur la programmation SAX
Présentation de l'API SAX pour le parcours de documents XML.
Principes
SAX permet un parcours générique d'un document XML, c'est-à-dire qu'il est indépendant du format.
SAX signifie Simple API for XML et est donc disponible dans différents langages de programmation, avec la même interface.
Le principe de SAX est simple : pour chaque ouverture ou fermeture d'élément, chaque feuille texte, etc. un événement ( event) est
déclenché. Le développeur doit simplement anticiper ces événements et leurs associer les instructions à effectuer lorsqu'ils se
déclencheront.
SAX parcourt le document XML dans l'ordre du document et active du code associé selon les événements qui se déclenchent. De plus,
contrairement à d'autres modèles de traitement XML (DOM, XPath et XSLT), SAX ne charge pas le document en mémoire mais se contente
de le parcourir. SAX est donc particulièrement adapté pour réaliser des traitements XML simples, en séquence, éventuellement sur des
fichiers XML très louds.
Introduction
DOM, pour Document Object Model, vise à fournir un modèle d'un document semi-structuré, autrement dit d'un document XML. Il s'agit en
particulier de définir des méthodes d'accès et de modification opérant sur un tel document.
DOM est défini par des recommandations du W3C, trois niveaux ont aujourd'hui été définis. Certaines parties de ces recommandations sont
dédiées au traitement de documents XHTML ; nous nous concentrons ici sur le noyau de DOM fournissant des méthodes valables pour tout
document XML.
En pratique, DOM permet de charger un document XML tout entier en mémoire et s'oppose sur ce point à SAX (qui permet de traiter un
document XML en une passe, sans occupation mémoire). Au minimum, DOM utilise une zone mémoire de la fichier XML lu ; dans les faits,
c'est souvent plus et cela pour se préparer à répondre de manière efficace à des interrogations complexes.
En Python, le programme minimal qui charge un document XML sous forme de DOM est le suivant :
from xml.dom.minidom import parse
import sys
xmlfilename = sys.argv[1]
dom = parse(xmlfilename)
Le modèle DOM reflète la nature arborescente des documents XML : il nous permet d'accéder à la racine ou à des noeuds quelconques,
d'obtenir les fils d'un noeud précis, ou encore ses frères. L'implémentation réelle du modèle présent en mémoire après le chargement du
document XML est cachée dans un objet et peut varier avec le langage de programmation utilisé. Par contre les méthodes d'accès et de
modification de l'arbre DOM sont standardisées par le W3C et sont donc les mêmes d'un langage à l'autre.
Pour terminer, précisons que chaque information présente dans le document d'origine se retrouve en mémoire comme un noeud de l'arbre
DOM : les éléments, les attributs, les textes, les commentaires, etc. sont autant de noeuds accessibles dans l'arbre DOM.
Obtenir un noeud
À partir de l'objet DOM, il est possible d'obtenir :
xmlfilename = sys.argv[1]
dom = parse(xmlfilename)
titres = dom.getElementsByTagName("titre")
premier = titres[0]
texte = premier.childNodes[0]
print texte.nodeValue
xmlfilename = sys.argv[1]
dom = parse(xmlfilename)
sites = dom.getElementsByTagName('site')
xmlfilename = sys.argv[1]
dom = parse(xmlfilename)
racine = dom.documentElement;
fils = racine.childNodes
print 'racine=',racine.nodeName
for f in fils:
if f.nodeType==1:
print f.nodeName,'=',f.childNodes[0].nodeValue
Modifier le DOM
Un nouveau DOM
impl = getDOMImplementation()
newdoc = impl.createDocument(None,"laracine",None)
top_element = newdoc.documentElement
copie = noeud.cloneNode(True)
copie.removeAttribute('nomattributasupprimer')