version 1.00, dernière mise à jour le 3 avril 2013.
XSL
signifie eXtensible Stylesheet Langage, ou langage extensible de feuille de style. Cette abréviation recouvre en fait trois langages :
XPath
désigne un moyen d'accéder à un nœud quelconque de l'arborescence d'un document XML
à partir d'un autre nœud quelconque.
XSLT
signifie eXtensible Stylesheet Langage Transformation.
XSL-FO
signifie eXtensible Stylesheet Langage - Formating Objects, et désigne un langage permettant le contrôle de la mise en page finale de la transformation. Ce langage est particulièrement destiné à la production de contenus au format PDF.
Dans le cadre d'une chaîne de production de contenu, il s'agit de transformer un document XML en un autre document XML. Ce cours se limite donc à l'utilisation de XSLT.
Il existe deux manières d'opérer la transformation d'un document XML
soit côté serveur, via une transformation statique ou dynamique : ce qui est délivré au navigateur est alors une page HTML
soit dynamiquement côté client, en liant une feuille de style au document, dans son prologue. On écrira ainsi par exemple...
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="feuilleDeStyle.xsl"?>
Voici un exemple de bibliographie :
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="biblio.xsl"?>
<biblio>
<livre>
<titre>Les Misérables</titre>
<auteur>Victor Hugo</auteur>
<nb_tomes>3</nb_tomes>
</livre>
<livre>
<titre>L'Assomoir</titre>
<auteur>Émile Zola</auteur>
</livre>
<livre lang="en">
<titre>David Copperfield</titre>
<auteur>Charles Dickens</auteur>
<nb_tomes>3</nb_tomes>
</livre>
</biblio>
La feuille de style associée est la suivante :
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output encoding="UTF-8" indent="yes" method="xml" />
<xsl:template match="/">
<livres>
<xsl:apply-templates />
</livres>
</xsl:template>
<xsl:template match="livre">
<livre>Le livre <xsl:value-of select="titre" /> a été écrit par <xsl:value-of select="auteur" />, et publié en <xsl:value-of select="nb_tomes" />
</livre>
</xsl:template>
</xsl:stylesheet>
L'élément racine est xsl:stylesheet
L'élément xsl:output
permet de spécifier un certain nombre d'options. Pour le moment, nous nous contenterons de celles-ci :
encoding
indique l'encodage
indent
permet d'indiquer si l'on souhaite en sortie un fichier indenté ou non
method
peut prendre les valeurs html, xml, text ou xhtml en fonction du type de sortie désiré (cela a un impact sur la gestion des éléments vides)
xsl:template
sert à remplacer tout ou partie du contenu XML de la page. On le rencontre ici en deux occasions : /
désigne l'intégralité du document XML d'entrée, et livre
permet de remplacer en sortie le contenu de l'élément livre
du document d'entrée par le contenu du template
xsl:value-of
enfin permet de lire une valeur depuis le document XML d'entrée.
Vous pouvez vérifier le document XML et la feuille de style associée.
XPath est un langage permettant de cibler les nœuds d'un document XML. Il propose de nombreuses fonctionnalités, mais nous n'allons aborder ici qu'un extrait de sa syntaxe dite « abrégée ».
L'exemple le plus simple d'expression de sélection est le nom d'un type d'élément. Cette expression sélectionne tous les éléments du type précisé descendant ou ancêtre d'un nœud donné. Exemple :
<xsl:value-of select="nom_element" />
L'opérateur /
permet de définir le chemin d'accès aux éléments à sélectionner, et donc leur parenté. Par exemple, section/paragraphe
sélectionne les éléments section
du nœud courant et pour chaque élément section
, sélectionne les éléments paragraphe
qu'il contient. En d'autres termes, cette expression sélectionne les petits-fils paragraphe
du nœud courant qui ont pour père un nœud section
.
Un nom d'élément peut être remplacé par *
dans une expression. Par exemple, */paragraphe
sélectionne tous les petits-fils paragraphe
quel que soit leur père.
L'utilisation de //
permet d'appliquer la recherche aux descendants et non pas seulement aux fils directs. Par exemple, section//paragraphe
sélectionne tous les éléments paragraphe
descendant d'un élément section
fils direct du nœud courant.
Le caractère .
sélectionne le nœud courant. Par exemple, .//paragraphe
sélectionne tous les descendants paragraphe
du nœud courant.
La chaîne ..
sélectionne le père du nœud courant. Par exemple, ../paragraphe
sélectionne tous les nœuds paragraphe
frères du nœud courant.
Considérons par exemple le fichier XML
suivant, l’élément courant étant l’élément racine A
:
<A>
<B>
<C>C1</C>
</B>
<B>
<C>C2</C>
</B>
<D>
<C>C3</C>
</D>
<E>
<B>
<C>C4</C>
</B>
</E>
<B>
<E>
<C>C5</C>
</E>
</B>
</A>
*/C
renvoie les éléments C1, C2 et C3
B/C
renvoie les éléments C1 et C2
B//C
renvoie les éléments C1, C2 et C5
.//B/C
renvoie les éléments C1, C2 et C4
L'expression comment()
sélectionne tous les nœuds commentaires fils du nœud courant.
L'expression text()
sélectionne tous les nœuds fils du nœud courant, ne contenant que du texte.
L'expression node()
sélectionne tous les nœuds fils du nœud courant.
L'expression id("UnIdentifiant")
sélectionne l'élément, normalement unique, qui a un attribut attr
de type ID (cf. le paragraphe "Déclaration d'attribut de type ID") valant "UnIdentifiant"
.
On peut aussi « naviguer » dans les branches de l'arborescence du document XML
, en utilisant les ressources du DOM. Différents types de syntaxes sont possibles, fondées sur une expression de la forme Element[Expression]
. Par exemple :
elt[i]
où i
est un nombre entier désigne le i
-ème descendant direct d'un même parent ayant le nom indiqué. Par exemple, paragraphe[3]
désigne le 3ème enfant de l'élément courant, portant le nom paragraphe
. Attention, la numérotation commence à 1 et non à 0.
elt[position()>i]
où i
est un nombre entier sélectionne tous les éléments précédés d'au moins i
éléments de même nom comme descendants du même parent. Par exemple, paragraphe[position()>5]
sélectionne tous les éléments paragraphe
dont le numéro d'ordre est strictement supérieur à 5.
elt[position() mod 2=1]
sélectionne tout élément qui est un descendant impair.
elt[souselt]
sélectionne tout élément elt
qui a au moins un descendant souselt
(à ne pas confondre avec elt/souselt
, qui sélectionne tout élément souselt
ayant pour parent elt
...).
Les attributs d'un élément sont sélectionnés en faisant précéder leur nom par le caractère @
. Les règles relatives à la sélection des éléments s'appliquent également aux attributs :
section/@titre
sélectionne l'attribut titre
de l'élément section
section[@titre]
sélectionne les éléments section
qui ont un attribut titre
.
section[@titre="Introduction"]
sélectionne les éléments section
dont l'attribut titre
a pour valeur Introduction
.
Si l'on veut afficher le contenu de l'attribut, on le fait précéder du caractère /
. Par exemple, <xsl:value-of select="paragraphe/@titre" />
permet l'affichage du titre de l'élément paragraphe fils de l'élément courant (si rien n'est précisé, par défaut il s'agit du premier élément paragraphe fils).
Les opérateurs logiques not()
, and
et or
peuvent être utilisés, comme par exemple section[not(@titre)]
, qui sélectionne les éléments section
qui n'ont pas d'attribut titre
. Attention : lorsque, dans la DTD
par exemple, l'attribut est défini comme ayant une valeur par défaut, même s'il n'est pas explicité dans le document XML
, il est considéré comme existant.
Cet élément de bouclage crée une boucle dans laquelle sont appliquées des transformations. Son utilisation est de la forme :
<xsl:for-each select="jeunœud">
</xsl:for-each>
select
correspond au jeu de nœuds devant être parcouru par la boucle. Exemple d'utilisation :
<ul>
<xsl:for-each select="item">
<li>
<xsl:value-of select="." />
</li>
</xsl:for-each>
</ul>
Cet élément permet d'effectuer un tri sur un jeu de nœuds. Il doit être placé soit dans un élément xsl:for-each
soit dans un élément xsl:apply-templates
. C'est un élément vide qui peut être appelé plusieurs fois pour effectuer un tri multicritères. Chaque appel à cet élément provoque un tri sur un champ spécifique, dans un ordre prédéfini. L'utilisation de cet élément est de la forme :
<xsl:sort select="nœud" data-type="text | number | elt" order="ascending | descending" lang="nmtoken" case-order="upper-first | lower-first" />
select
permet de spécifier un nœud comme clé de tri.
data-type
correspond au type des données à trier. Dans le cas où le type est number
, les données sont converties puis triés.
order
correspond à l'ordre de tri. Cet attribut vaut ascending
ou descending
.
Par exemple :
<ul>
<xsl:for-each select="livre">
<xsl:sort select="auteur" order="descending" />
<li>
<b>
<xsl:value-of select="auteur" />
</b>
<br />
<xsl:value-of select="titre" />
</li>
</xsl:for-each>
</ul>
Dans cet exemple, la liste des livres est classée dans l'ordre alphabétique décroissant des noms d'auteur.
Cet élément permet la fragmentation du modèle dans certaines conditions. Il est possible de tester la présence d'un attribut, d'un élément, de savoir si un élément est bien le fils d'un autre, de tester les valeurs des éléments et attributs. L'utilisation de cet élément est de la forme :
<xsl:if test="condition">action</xsl:if>
test
prend la valeur 1
ou 0
suivant le résultat de la condition (vrai ou faux). action
correspond à l'action devant être effectuée (texte à afficher, second test, gestion de chaîne...). Exemples d'utilisation : <xsl:if test="@âge=’24’>Cette personne a 24 ans.</xsl:if>
, ou :
<xsl:if test="livre">
<ul>
<xsl:for-each select="livre">
<li>
<b>
<xsl:value-of select="auteur" />
<br />
</b>
<xsl:value-of select="titre" />.<xsl:if test="@langue='français'">Ce livre est en français.</xsl:if>
</li>
</xsl:for-each>
</ul>
</xsl:if>
Dans le code précédent, si l'attribut langue
de l'élément livre
vaut français
, le processeur ajoutera au fichier de sortie la phrase "Ce livre est en français". Il ne se passe rien si ce n'est pas le cas.
Cet élément permet de définir une liste de choix et d'affecter à chaque choix une transformation différente. Chaque choix est défini par un élément xsl:when>
et un traitement par défaut peut être spécifié grâce à l'élément xsl:otherwise
. Exemple d'utilisation :
<ul>
<xsl:for-each select="livre">
<li>
<b>
<xsl:value-of select="auteur" />
<br />
</b>
<xsl:value-of select="titre" />
<xsl:choose>
<xsl:when test="@langue='francais'">Ce livre est en français.</xsl:when>
<xsl:when test="@langue='anglais'">Ce livre est en anglais.</xsl:when>
<xsl:otherwise>Ce livre est dans une langue non répertoriée.</xsl:otherwise>
</xsl:choose>
</li>
</xsl:for-each>
</ul>
Cette création est mise à disposition par Gilles Chagnon sous un contrat Creative Commons.