66. Découverte de XSLT

66.1. XPath

66.1.1. Document XML utilisé

Pour illustrer les possibilités des expressions XPath nous allons utiliser le document livre.xml. Voici le contenu de ce document :

<?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>
	<commentaire>Intrigue passionante.</commentaire>
	<commentaire>Suspense garanti.</commentaire>
</livre>

66.1.2. Éléments PHP utilisés

Nous allons utiliser l’objet DOMXPath et sa méthode query() pour évaluer nos expressions XPath. Le constructeur de DOMXPath prend un objet DOMDocument en paramètre. C’est par rapport à ce document que sera évaluée l’expression XPath.

66.1.3. Le langage XPath

Le langage XPath n’a pas d’utilisation propre il est toujours utilisé par d’autres langages (comme le XSLT). Son rôle est d’identifier des parties d’un document XML.

Il permet aux programmes XSLT d’accéder aux différents noeuds (nodes) ou des ensembles de noeuds (node-sets). De l’évaluation de ces expressions résulte une donnée textuelle, un noeud ou une sous-arborescence.

Les expressions XPath sont une succession d’étapes séparées par des "/" (e.g /etape1/etape2). Le fonctionnement est similaire au système de fichiers Unix. De la même façon la présence du premier "/" permet de savoir si l’expression est relative au contexte (s’il est absent) ou absolue (s’il est présent).

Chaque étape est de la forme :


axe::filtre[predicat1][predicat2]...

  • l’axe : détermine le sens de parcours par rapport au noeud contexte.

  • le filtre : détermine le type de noeuds qui seront retenus. Le type de noeuds couvre les éléments et leurs attributs mais également les contenus textuels et les commentaires.

  • les prédicats : ils sont optionnels et permettent de limiter la sélection des noeuds résultats. Pour cela ils expriment un certain nombre de règles que doivent respecter les noeuds.

66.1.4. Les axes

Les principaux axes utilisés sont les suivants :

Tableau 10. Les principaux axes

Axe

Description

Abréviation

self

Désigne le noeud contexte.

.

child

Désigne les fils du noeud contexte (enfants immédiats). Il s’agit de l’axe par défaut, il peut donc être omis.

par défaut

parent

Désigne le père du noeud contexte.

..

descendant

Désigne tous les noeuds descendants du noeud contexte.

//

descendant-or-self

Désigne tous les noeuds descendants et le noeud contexte.

ancestor

Désigne tous les noeuds ancêtres du noeud contexte.

ancestor-or-self

Désigne tous les noeuds ancêtres et le noeud contexte.

attribute

Désigne les attributs du noeud contexte.

@

preceding

Désigne les noeuds précédant le noeud contexte.

aucun

following

Désigne les noeuds suivant le noeud contexte.

aucun

preceding-sibling

Désigne les noeuds frères (même type d’élément) précédant le noeud contexte.

aucun

following-sibling

Désigne les noeuds frères (même type d’élément) suivant le noeud contexte.

aucun

66.1.5. Les filtres

Les filtres peuvent être définis de deux sortes :

  • ceux par nom de noeud

  • ceux par type de noeud.

Les filtres par nom précisent directement le nom du noeud ou de l’attribut. En voici quelques exemples :


/livre/auteur
/livre/@ISBN
description/epoque

Les filtres par type de noeuds sont les suivants :

Tableau 11. Les principaux filtres

Filtre

Description

text()

Designe les noeuds de type texte.

comment()

Designe les noeuds commentaires.

processing-instruction()

Designe les noeuds de type instruction de traitement.

node()

Designe tous les noeuds quelque soit leur type.

*

Designe tous les types sauf les attributs ou tous les attributs s’il est précédé de l’axe des attributs.

66.1.6. Les prédicats

Les prédicats sont des expressions dont le résultats est un booléen ; Les prédicats les plus courants sont les suivants :

Tableau 12. Les principaux prédicats

Prédicat

Description

Abréviation

/livre[auteur]

Teste l’existance d’un noeud.

aucune

/livre/commentaire[position()=1]

Recherche un noeud fonction de sa position dans le contexte.

/livre/commentaire[1]

/livre[@ISBN='2-99999-123-4']

Teste la valeur du noeud par rapport à une valeur textuelle ou numérique.

aucune

Les prédicats peuvent utiliser les expressions logiques and et or. Il est aussi possible d’utiliser de façon successive des prédicats. Dans ce cas le prédicat s’applique sur les noeuds qui vérifient les prédicats qui le précèdent.

66.1.7. Les fonctions

Le langage XPath dispose d’un certain nombre de fonctions dont voici celles présentes dans toutes les implémentations :

66.1.7.1. Gestion des ensembles de noeuds (node-set)

Tableau 13.

Fonction

Description

last()

Retourne l’indice du dernier élément.

position()

Retourne l’indice de l’élément considéré.

count(expression)

Nombre de noeuds pour lesquels l’expression est vrai.

66.1.7.2. Chaînes de caractères

Tableau 14.

Fonction

Description

string(objet)

Converti l’objet passé en paramètre en chaîne de caractères.

concat(s1,...,sn)

Concatène les chaînes de caractères passées en paramètres.

count(expression)

Nombre de noeuds pour lesquels l’expression et vrai.

starts-with(s1,s2)

Indique si la chaîne s1 commence par la chaîne s2.

contains(s1,s2)

Indique si la chaîne s1 contient la chaîne s2.

substring(s1,debut[,taille])

Permet d’extraire une sous chaîne dont l’indice de début est précisé et la taille est optionnelle (par défaut tout le reste). Attention l’indice commence à 1 et non à 0.

string-length(s)

Retourne la taille de la chaîne.

66.1.7.3. Nombres

Tableau 15.

Opérateur/Fonction

Description

+

Addition de deux types numériques. A + B

*

Multiplication de deux types numériques. A * B

-

Soustraction de deux types numériques (attention aux espaces s’ils ne sont pas présents l’interprétation peut-être faussée). A - B

div

Division de deux types numériques. A div B

mod

Modulo de deux types numériques. A mod B

number(objet)

Converti l’objet en nombre.

sum(expression)

Retourne la somme des noeuds de l’expression.

floor(number)

Retourne l’entier supérieur.

ceil(number)

Retourne l’entier inférieur.

round(number)

Arrondi l’entier.

Il existe en plus de ces fonctions la fonction not() qui va permettre de réaliser une inversion logique.

66.2. Document XML pour la transformation XSL

Nous allons travailler à partir d’un document RSS. Nous utiliserons la version 2.0 qui est sous licence Creative Commons. Il s’agit d’un format de syndication de contenu, il en existe d’autres dont le format ATOM soutenu par l’IETF (Internet Engineering Task Force)

<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0">
	<channel>
		<title>Actualités de l’école ouverte francophone</title>
		<link>http://eof.eu.org/</link>
		<description>L’école ouverte francophone</description>
		<language>fr-FR</language>
		<pubDate>Wed, 28 Sep 2005 20:00:00 GMT</pubDate>
		<lastBuildDate>Wed, 21 Sep 2005 09:41:01 GMT</lastBuildDate>
		<docs>http://blogs.law.harvard.edu/tech/rss</docs>
		<generator>Un generateur</generator>
		<managingEditor>info@eof.eu.org</managingEditor>
		<webMaster>info@eof.eu.org</webMaster>
		<item>
			<title>Inauguration de l’ÉOF</title>
			<description>
				L’Ecole Ouverte Francophone (ÉOF) a été fondée en 2003 afin de créer un programme de formation sur les logiciels libres,
				débouchant sur une certification professionnelle. Elle sera officiellement inaugurée par Monsieur le Président du Conseil
				Régional du Limousin le mardi 27 septembre 2005, à Ester Technopole.
			</description>
			<pubDate>Wed, 21 Sep 2005 09:39:21 GMT</pubDate>
			<guid>http://eof.eu.org/article.php3?id_article=92</guid>
		</item>
		<item>
			<title>Une liste de diffusion EOF est créée... inscrivez-vous !</title>
			<link>http://eof.eu.org/rubrique.php3?id_rubrique=7</link>
			<description>
				La liste eof-annonce@eof.eu.org est créée, elle vous permettra de recevoir toutes les news de l’EOF, mais aussi de poser
				vos questions et de recevoir rapidement des réponses.
			</description>
			<pubDate>Mon, 18 Jul 2005 15:25:56 GMT</pubDate>
			<guid>http://eof.eu.org/article.php3?id_article=86</guid>
		</item>
		<item>
			<title>FAQ en ligne</title>
			<link>http://eof.eu.org/rubrique.php3?id_rubrique=9</link>
			<description>
				Vous avez des questions ? Vérifiez dans la FAQ avant de nous interroger, vous y trouverez peut-être des réponses.
			</description>
			<pubDate>Fri, 08 Jul 2005 10:38:18 GMT</pubDate>
			<guid>http://eof.eu.org/article.php3?id_article=77</guid>
		</item>
		<item>
			<title>L’EOF est une réalité... attention au départ... prêt... partez...</title>
			<description>
				L’EOF prend forme, sa vie commence, le dispositif de formation à distance est en place et la plateforme de formation
				Amarante avance à grands pas.
			</description>
			<pubDate>Mon, 27 Jun 2005 14:27:45 GMT</pubDate>
			<guid>http://eof.eu.org/article.php3?id_article=67</guid>
		</item>
	</channel>
</rss>

66.2.1. Processeur XSLT

Pour illustrer les exemples que nous allons utiliser l’objet XSLTProcessor. Le script suivant va vous permettre de procéder simplement à la transformation.

<?php
	$xmlDocument = new DOMDocument();
	$xsltDocument = new DOMDocument();
	$xmlDocument->load($_GET["xml"]);
	$xsltDocument->load($_GET["xslt"]);
	$processeurXSLT = new XSLTProcessor();
	$processeurXSLT->importStyleSheet($xsltDocument);
	echo $processeurXSLT->transformToXML($xmlDocument);
?>

Pour obtenir le résultat de la transformation, appelez ce script depuis votre navigateur en lui passant deux paramètres.

Le paramètre xml pour le document à transformer et le paramètre xslt pour le document XSLT.


http://192.168.0.10/eof/si022/td_xsl/transformation.php?xml=eof.rss&xslt=rss2html_01.xsl

Si l'on préfère utiliser un outil en ligne de commande on peut utiliser xsltproc qui est fourni avec la librairie libxslt.

Il suffit pour l’utiliser de saisir la commande suivante :

[adminbdd html]$ xsltproc -o fichier_resultat.html documentXSLT.xsl DocumentXML.xml

66.3. Le langage XSLT

Un programme XSLT est un document XML qui va nous permettre de réaliser la transformation d’un autre document XML. Ils doivent cependant tous deux être bien formés.

Le terme de document XSLT est aussi utilisé pour désigner un programme XSLT. L’exemple suivant va permettre d’en voir la structure générale :

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/rss/channel">
		<html>
			<head>
				<title>Actualités de l’éof</title>
			</head>
		<body>
			<xsl:for-each select="item">
				<h1><xsl:value-of select="title"/></h1>
				<p><xsl:value-of select="description"/></p>
			</xsl:for-each>
		</body>
		</html>
	</xsl:template>
</xsl:stylesheet>

Tout document XSLT dispose d’un élément racine xsl:stylesheet qui comporte les attributs version et xmlns. Dans notre exemple la version est la 1.0 et cette spécification associe l’espace de nom xsl aux éléments XSLT.

La dernière version de XSLT est la version 2.0 mais elle est encore peu supportée par les processeurs XSLT. Nous nous limiterons donc à la version gérée par notre processeur, c’est à dire la version 1.0.

Les enfants directes de l’élément racine sont appelés "top-level elements" ou éléments de haut niveau. Ils vont permettre : de définir des variables, indiquer le format de sortie, etc.

Dans notre exemple xsl :template en est une illustration, il sert à définir une "règle modèle" qui s’appliquera au noeud défini à l’aide de son attribut match.

On trouve ensuite le contenu littéral du modèle qui va-t-être enrichi grâce au programme XSLT et au document XML. Pour cela on va utiliser un autre type d’élément XSLT, les instructions. Ici xsl:for-each et xsl:value-of (l’une est un élément conteneur l’autre un élément vide).

Figure 54. Transformation réalisée par le navigateur

Ou via la ligne de commande :

[adminbdd html]$ xsltproc -o fichier_resultat.html model.xsl flux.rss; cat fichier_resultat.html
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>Actualités de l’éof</title>
	</head>
	<body>
		<h1>Inauguration de l’ÉOF</h1>
		<p>
			L’Ecole Ouverte Francophone (ÉOF) a été fondée en 2003 afin de créer un programme de formation sur les logiciels libres,
			débouchant sur une certification professionnelle. Elle sera officiellement inaugurée par Monsieur le Président du Conseil
			Régional du Limousin le mardi 27 septembre 2005, à Ester Technopole.
		</p>
		<h1>Une liste de diffusion EOF est créée... inscrivez-vous !</h1>
		<p>
			La liste eof-annonce@eof.eu.org est créée, elle vous permettra de recevoir toutes les news de l’EOF, mais aussi de poser
			vos questions et de recevoir rapidement des réponses.
		</p>
			<h1>FAQ en ligne</h1>
		<p>
			Vous avez des questions ? Vérifiez dans la FAQ avant de nous interroger, vous y trouverez peut-être des réponses.
		</p>
			<h1>L’EOF est une réalité... attention au départ... prêt... partez...</h1>
		<p>
			L’EOF prend forme, sa vie commence, le dispositif de formation à distance est en place et la plateforme de formation
			Amarante avance à grands pas.
		</p>
	</body>
</html>

66.4. Éléments de haut niveau

66.4.1. xsl:template

Cet élément permet de définir les règles qui seront prisent en compte lors de la transformation du document. Il dispose de quatre attributs tous optionnels :

  • L’attribut match contient le motif ou pattern qui va permettre d’indiquer les noeuds auxquels s’applique la règle.

  • L’attribut name permet de nommer la règle. Il sera ensuite possible de l’appeler avec l’élément xsl:calltemplate.

    n.b : Les attributs match et name s’excluent mutuellement et ne doivent pas être présents dans une même règle.

  • L’attribut mode permet de définir la catégorie de la règle. On va ainsi pouvoir avoir plusieurs règles avec un même motif mais qui le présenteront de façons différentes. Pour que le mode soit pris en compte il doit être précisé lors de l’appel avec l’élément xsl:apply-templates.

  • L’attribut priority permet de définir quelle règle utiliser si plusieurs sont applicables. Par défaut la règle a une priorité de 0. Plus la valeur est grande et plus la règle est prioritaire. Il est aussi possible de mettre des priorités négatives.

    n.b : Les processeurs XSLT disposent de règles implicites qui en cas d’absence de règles utilisateurs, vont afficher le contenu des différents éléments.

Voici un exemple :

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/">
	</xsl:template>
</xsl:stylesheet>

Avec cet exemple, vous obtenez un document résultat vide. En effet la règle s’applique à tout notre arbre XML et ne précise rien. Nous pouvons placer un contenu littéral pour agrémenter l’affichage.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/">
		<html>
			<head><title>TD XSL</title></head>
			<body>
				<h1>Exemple de contenu</h1>
				<p>Contenu statique produit sans ternir compte du contenu du document initial.</p>
			</body>
		</html>
	</xsl:template>
</xsl:stylesheet>

Figure 55. Autre exemple simple

66.4.2. xsl:apply-templates

Cet élément permet de préciser pour un ensemble de noeuds le modèle à appliquer. Il dispose de deux attributs optionnels :

  • L’attribut select qui prend une expression XPath comme valeur. Une fois évaluée elle donne l’ensemble de noeuds concernés.

    n.b : L’attribut select dispose d’une valeur par défaut qui correspond à tous les noeuds enfants à l’exception des attributs.

  • L’attribut mode permet de définir la catégorie de la règle.

Modifions notre exemple précédent pour intégrer ce nouvel élément :

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/">
		<html>
			<head><title>TD XSL</title></head>
			<body>
				<h1>Les actualités de l’EOF</h1>
				<xsl:apply-templates />
			</body>
		</html>
	</xsl:template>
</xsl:stylesheet>

Nous obtenons l’intégralité des éléments de notre document de travail. Si vous éditez la source à l’aide de votre navigateur vous voyez le même contenu mais présenté avec la forme arborescente du fichier RSS. Les niveaux de l’arbre XML sont traduits par l’indentation des contenus.

Figure 56.

Nous allons maintenant restreindre l’affichage aux seuls titres des actualités :

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/">
		<html>
			<head><title>TD XSL</title></head>
			<body>
				<h1>Les actualités de l’EOF</h1>
				<xsl:apply-templates select="//item" />
			</body>
		</html>
	</xsl:template>
	<xsl:template match="item">
		<xsl:apply-templates select="title" />
		<br />
	</xsl:template>
</xsl:stylesheet>

Figure 57. Affichage uniquement des titres

66.4.3. xsl:call-template

Cet élément permet d’appeler des règles définies avec l’élément xsl:template et son attribut name. il est principalement utilisé pour factoriser des instructions au sein d’un programme XSLT. En plus d’afficher le titre des actualités nous allons maintenant afficher leur synopsis :

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/">
		<html>
			<head><title>TD XSL</title></head>
			<body>
				<h1>Les actualités de l’EOF</h1>
				<xsl:apply-templates select="//item" />
			</body>
		</html>
	</xsl:template>
	<xsl:template match="item">
		<xsl:apply-templates />
	</xsl:template>
	<xsl:template match="title">
		<h2><xsl:call-template name="affichage" /></h2>
	</xsl:template>
	<xsl:template match="description">
		<xsl:call-template name="affichage" />
	</xsl:template>
	<xsl:template match="link|pubDate|guid" />
	<xsl:template name="affichage">
		<xsl:apply-templates /><br />
	</xsl:template>
</xsl:stylesheet>

Nous avons ainsi dans cet exemple factorisé la méthode d’affichage des éléments title et description. On notera la façon d’appliquer plusieurs motifs à une même règle en les séparant par le caractère "|". Cette règle est présente dans notre programme uniquement pour s’assurer que les éléments link, pubDate et guid ne s’afficheront pas. Si elle n’était pas présente le processeur XSLT afficherait ces éléments.

66.4.4. xsl:output

Cet élément va permettre de préciser le format du document résultat. Il dispose d’un attribut method qui peut prendre trois valeurs : xml, html, text. Le format xml est celui pris par défaut.

L’attribut version permet de préciser celle que l’on souhaite associer aux documents xml ou html.

L’attribut indent permet d’indenter le code lorsqu’il s’agit de sorties xml ou html.

Il est possible de préciser l’encodage que l’on souhaite utiliser dans le document résultat à l’aide de l’attribut encoding.

n.b : L’utilisation de l’attribut method avec la valeur html tend à devenir obsolète.

Exécutez la transformation avec le code suivant :

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="text" />
	<xsl:template match="/">
		<html>
			<head><title>TD XSL</title></head>
			<body>
				<h1>Les actualités de l’EOF</h1>
				<xsl:apply-templates select="//item" />
			</body>
		</html>
	</xsl:template>
	<xsl:template match="item">
		<xsl:apply-templates />
	</xsl:template>
	<xsl:template match="title">
		<h2><xsl:call-template name="affichage" /></h2>
	</xsl:template>
	<xsl:template match="description">
		<xsl:call-template name="affichage" />
	</xsl:template>
	<xsl:template match="link|pubDate|guid" />
	<xsl:template name="affichage">
		<xsl:apply-templates /><br />
	</xsl:template>
</xsl:stylesheet>

Vous obtenez un texte compact sans mise en forme. Éditez la source de votre page, vous constaterez que les balises ont été supprimées. Procédez de la même façon en affectant "html" à l’attribut method et vous constaterez que le code XHTML sera modifié en HTML. Par exemple les balises <br/> seront transformées en <br>.

[adminbdd html]$ xsltproc -o fichier_resultat.html model.xsl flux.rss; cat fichier_resultat.html
TD XSLLes actualités de l’EOF Inauguration de l’ÉOF L’Ecole Ouverte Francophone (ÉOF) a été fondée en 2003 afin de créer un programme de formation 
sur les logiciels libres, débouchant sur une certification professionnelle. Elle sera officiellement inaugurée par Monsieur le Président du Conseil
Régional du Limousin le mardi 27 septembre 2005, à Ester Technopole. Une liste de diffusion EOF est créée... inscrivez-vous ! La liste eof-annonce@eof.eu.org
est créée, elle vous permettra de recevoir toutes les news de l’EOF, mais aussi de poser vos questions et de recevoir rapidement des réponses. FAQ en ligne
Vous avez des questions ? Vérifiez dans la FAQ avant de nous interroger, vous y trouverez peut-être des réponses. L’EOF est une réalité... attention au
départ... prêt... partez... L’EOF prend forme, sa vie commence, le dispositif de formation à distance est en place et la plateforme de formation Amarante
avance à grands pas.

66.5. Les instructions

Le XSLT comme tout langage de programmation dispose d’un certain nombre d’instructions.

66.5.1. xsl:if

Cette instruction va permettre de réaliser un test. Elle dispose d’un seul paramètre test qui prend comme valeur une expression XPath. L’expression est évaluée puis convertie sous forme d’un booléen.

n.b : contrairement à d’autres langages de programmation le XSLT ne dispose pas de l’instruction else. Si vous avez un tel besoin alors l’instruction xsl:choose sera plus adaptée.

Dans notre exemple nous allons maintenant contrôler la langue du document transmis avant de l’afficher.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" indent="yes" />
	<xsl:template match="/">
		<html>
			<head><title>TD XSL</title></head>
			<body>
				<h1>Les actualités de l’EOF</h1>
				<xsl:if test="/rss/channel/language = 'fr-FR'">
					<xsl:apply-templates select="//item" />
				</xsl:if>
			</body>
		</html>
	</xsl:template>
	<xsl:template match="item">
		<xsl:apply-templates />
	</xsl:template>
	<xsl:template match="title">
		<h2><xsl:call-template name="affichage" /></h2>
	</xsl:template>
	<xsl:template match="description">
		<xsl:call-template name="affichage" />
	</xsl:template>
	<xsl:template match="link|pubDate|guid" />
	<xsl:template name="affichage">
		<xsl:apply-templates /><br />
	</xsl:template>
</xsl:stylesheet>

66.5.2. xsl:choose

Cette instruction va permettre de proposer plusieurs évaluations successives et si aucune ne correspond d’en proposer une par défaut.

Le système d’évaluation est identique à celui du xsl:if. L’élément xsl:choose est sans attribut mais il peut contenir deux types d’éléments :

  • xsl:when qui évaluera l’expresion XPath de son attribut test. Cet élément doit au moins être présent une fois.

  • xsl:otherwise qui sera appelé si aucune des évaluations n’a abouti.

n.b : Dès qu’une des expressions XPath est vérifiée alors le processus est interrompu et ce même si plusieurs d’entre elles correspondaient.

Voici l’exemple précédent revu avec cet élément. Modifiez l’élément language du document RSS pour voir les changements produits :

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" indent="yes" />
	<xsl:template match="/">
		<html>
			<head><title>TD XSL</title></head>
			<body>
				<h1>Les actualités de l’EOF</h1>
				<xsl:choose>
					<xsl:when test="/rss/channel/language='fr-FR'">
						<xsl:apply-templates select="//item" />
					</xsl:when>
					<xsl:otherwise>
						<h2>Les actualités fournies ne sont pas au bon format.</h2>
					</xsl:otherwise>
				</xsl:choose>
			</body>
		</html>
	</xsl:template>
	<xsl:template match="item">
		<xsl:apply-templates />
	</xsl:template>
	<xsl:template match="title">
		<h2><xsl:call-template name="affichage" /></h2>
	</xsl:template>
	<xsl:template match="description">
		<xsl:call-template name="affichage" />
	</xsl:template>
	<xsl:template match="link|pubDate|guid" />
	<xsl:template name="affichage">
		<xsl:apply-templates /><br />
	</xsl:template>
</xsl:stylesheet>

Figure 58. Modification code langage

66.5.3. xsl:for-each

Cette instruction va nous permettre de faire des itérations en fonction d’une expression XPath. L’élément dispose d’un seul paramètre select qui permet de fournir cette expression. Modifions notre exemple en conséquence.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" indent="yes" />
	<xsl:template match="/">
		<html>
			<head><title>TD XSL</title></head>
			<body>
				<h1>Les actualités de l’EOF</h1>
				<xsl:choose>
					<xsl:when test="/rss/channel/language='fr-FR'">
						<xsl:apply-templates select="//channel" />
					</xsl:when>
					<xsl:otherwise>
						<h2>Les actualités fournies ne sont pas au bon format.</h2>
					</xsl:otherwise>
				</xsl:choose>
			</body>
		</html>
	</xsl:template>
	<xsl:template match="channel">
		<xsl:for-each select="item">
			<h2><xsl:value-of select="title" /></h2>
			<p><xsl:value-of select="description" /></p>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>

66.5.4. xsl:value-of

Nous avons utilisé cette instruction dans notre exemple précédent et son utilisation est assez intuitive. Elle permet d’évaluer une expression XPath et d’en afficher le résultat. L’expression est fournie dans le paramètre select.

66.5.5. xsl:attribute

Il est possible grâce à cette instruction d’insérer un attribut dans un élément du document résultat. Son seul paramètre est name qui permet d'indiquer le nom de l’attribut dans le document final.

Pour illustrer son utilisation ajoutons la description du flux RSS au document.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" indent="yes" />
	<xsl:template match="/">
		<html>
			<head>
				<title>TD XSL</title>
				<meta name="description">
					<xsl:attribute name="content">
						<xsl:value-of select="rss/channel/description" />
					</xsl:attribute>
				</meta>
			</head>
			<body>
				<h1>Les actualités de l’EOF</h1>
				<xsl:choose>
					<xsl:when test="/rss/channel/language = 'fr-FR'">
						<xsl:apply-templates select="//channel" />
					</xsl:when>
					<xsl:otherwise>
						<h2>Les actualités fournies ne sont pas au bon format.</h2>
					</xsl:otherwise>
				</xsl:choose>
			</body>
		</html>
	</xsl:template>
	<xsl:template match="channel">
		<xsl:for-each select="item">
			<h2><xsl:value-of select="title" /></h2>
			<p><xsl:value-of select="description" /></p>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>

Pour voir le résultat, affichez le code source de votre page. Vous trouverez la balise suivante :

<meta name="description" content="L'école ouverte francophone">

66.5.6. Autres instructions

66.5.6.1. xsl:element

Cette instruction va permettre de créer un élément. Elle sert principalement quand le nom de l’élément à créer n’est pas connu à l’avance.

66.5.6.2. xsl:copy

Permet la copie d’un élément. Si l’on considère le document XML et le programme XSLT suivants :

<pere>
	<enfant>descriptif enfant</enfant>
	descriptif pere
</pere>

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="pere">
		<xsl:copy />
	</xsl:template>
</xsl:stylesheet>

Seul l’élément pere est copié.

66.5.6.3. xsl:copy-of

Il s’agit ici d’une copie en profondeur, soit l’élément lui-même et ses descendants :

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="pere">
		<xsl:copy-of select="." />
	</xsl:template>
</xsl:stylesheet>

Cette fois tout le document XML est copié.

66.5.6.4. xsl:sort

Les éléments xsl:apply-template et xsl:for-each disposent de cet élément pour effectuer un tri sur leur résultat. Pour cela il est important que l’élément xsl:sort soit placé immédiatement après l’un d’eux.

Il dispose des attributs suivants :

  • select : sa valeur est une expression XPath sur laquelle s’effectue le tri.

  • data-type : il va permettre de préciser la nature de la donnée sur laquelle s’effectue le tri. Par exemple number pour traiter des valeurs numériques. Par défaut il utilise la valeur text.

  • order : pour préciser si le tri est croissant ou décroissant (ascending ou descending).

Si nous reprenons l’exemple du xsl:foreach nous obtenons le code suivant :

<xsl:template match="channel">
	<xsl:for-each select="item">
		<xsl:sort select="title" />
		<h2><xsl:value-of select="title" /></h2>
		<p><xsl:value-of select="description" /></p>
	</xsl:for-each>
</xsl:template>

n.b : Il est possible d'imbriquer plusieurs éléments de ce type. Dans ce cas les tris suivants conservent ceux déjà effectués.

66.5.6.5. xsl:param

Cet élément va permettre de passer un paramètre si le processeur XSLT le supporte. Cet élément dispose de deux attributs :

  • name : indique le nom du paramètre passé et qui sera utilisé dans la feuille de style.

  • select : permet de passer une valeur par défaut, prise en compte si le paramètre n’est pas défini.

L’appel se fait de la même façon qu’en PHP.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:param name="nom" />
        <xsl:template match="/">
                hello <xsl:value-of select="$nom" />
        </xsl:template>
</xsl:stylesheet>

66.6. Exercice d’application

Le menu d’un site nous est fourni sous forme d’un document XML. Réalisez le programme XSLT qui va permettre de le transformer en menu XHTML.

Voici le document XML à transformer :

<?xml version="1.0" encoding="utf-8" ?>
<navigation>
	<menu titre="menu1">
		<sous-menu titre="sous menu 1">
			<lien url="http://www.google.fr">Google</lien>
			<lien url="http://www.yahoo.fr">Yahoo</lien>
		</sous-menu>
		<sous-menu titre="sous menu 2">
			<lien url="http://www.wikipedia.org">Wikipédia</lien>
			<lien url="http://fr.wikipedia.org">Wikipédia France</lien>
		</sous-menu>
	</menu>
	<menu titre="menu2">
		<lien url="http://www.linuxfr.org">Linux FR</lien>
	</menu>
	<menu titre="menu3">
		<lien url="http://eof.eu.org/">L’école ouverte francophone</lien>
 	</menu>
</navigation>

Le document résultant devra être le suivant :

<?xml version="1.0"?>
<html>
	<head>
		<title>Menu</title>
	</head>
	<body>
		<ul>
			<li>menu1<ul>
				<li>sous menu 1<ul>
					<li><a href="http://www.google.fr">Google</a></li>
					<li><a href="http://www.yahoo.fr">Yahoo</a></li>
				</ul></li>
                <li>sous menu 2<ul>
					<li><a href="http://www.wikipedia.org">Wikip&#xE9;dia</a></li>
					<li><a href="http://fr.wikipedia.org">Wikipédia France</a></li>
				</ul></li>
			</ul></li>
			<li>menu2<ul>
				<li><a href="http://www.linuxfr.org">Linux FR</a></li>
			</ul></li>
			<li>menu3<ul>
				<li><a href="http://eof.eu.org/">L’école ouverte francophone</a></li>
			</ul></li>
		</ul>
	</body>
</html>

Voici le fichier XSL réalisé pour les besoins de l'exercice :

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8" />
	<xsl:template match="/">
		<html>
			<head>
				<title>Exercice d'application XSL</title>
			</head>
			<body>
				<xsl:apply-templates />
			</body>
		</html>
	</xsl:template>

	<xsl:template match="/navigation">
		<ul>
			<xsl:for-each select="menu">
				<li><xsl:value-of select="@titre" /><ul>
					<xsl:for-each select="sous-menu">
						<li><xsl:value-of select="@titre" /><ul>
							<xsl:apply-templates />
						</ul></li>
					</xsl:for-each>
				</ul></li>
			</xsl:for-each>
		</ul>
	</xsl:template>

	<xsl:template match="lien">
		<li>
			<a>
				<xsl:attribute name="href">
					<xsl:value-of select="@url" />
				</xsl:attribute>
				<xsl:value-of select="." />
			</a>
		</li>
	</xsl:template>
</xsl:stylesheet>

Exemple de rendu :

vanvincq@Debian-Laptop ~/Documents/CPLL/JournalDeBord/index_multi_page/exercices $ xsltproc transformation_xslt.xsl transformation_xslt.xml
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Exercice d'application XSL</title>
	</head>
	<body><ul>
		<li>menu1<ul>
			<li>sous menu 1<ul>
		        <li><a href="http://www.google.fr">Google</a></li>
		        <li><a href="http://www.yahoo.fr">Yahoo</a></li>
		    </ul></li>
			<li>sous menu 2<ul>
		        <li><a href="http://www.wikipedia.org">Wikipédia</a></li>
		        <li><a href="http://fr.wikipedia.org">Wikipédia France</a></li>
		    </ul></li>
		</ul></li>
		<li>menu2<ul></ul>
		</li>
		<li>menu3<ul></ul>
		</li>
		</ul>
	</body>
</html>

Pour ceux que cela intéressent, voici les fichiers sources :