Pour effectuer une transformation XML vers XML, le principe est le même que pour la transformation de XML vers HTML. La source est dans les deux cas du XML ce qui simplifie déjà les choses. Le format de sortie se fixe soit en paramètre de xsltproc ou du processeur XSLT que vous allez utiliser, ou comme dans l'exemple suivant en signalant XML dans le format de sortie, ligne 5.
1 <?xml version="1.0" encoding="ISO-8859-1"?> 2 3 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 4 <xsl:output method="xml" 5 encoding="ISO-8859-1" 6 doctype-public="-//W3C//DTD XHTML 1.1//EN" 7 doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" 8 indent="yes" 9 /> 10 <xsl:param name="nb_news">20</xsl:param> 11 12 <xsl:template match="/news"> 13 <body> 14 <xsl:apply-templates select="./title" mode="title"/> 15 <table class="news"> 16 <xsl:apply-templates select="./item[$nb_news >= position()]"/> 17 </table> 18 </body> 19 </xsl:template> 20 21 <xsl:template match="/news/item"> 22 <tr> 23 <td class="news"> 24 <xsl:apply-templates select="date" mode="date"/> 25 </td> 26 <td class="news"> 27 <xsl:apply-templates select="text"/> 28 </td> 29 </tr> 30 </xsl:template> 31 32 <xsl:template match="@*|node()" mode="date"> 33 <xsl:value-of select="day/node()"/> 34 <xsl:text>/</xsl:text> 35 <xsl:value-of select="month/node()"/> 36 <xsl:text>/</xsl:text> 37 <xsl:value-of select="year/node()"/> 38 </xsl:template> 39 40 <xsl:template match="/news/title" mode="title"> 41 <h1> 42 <xsl:apply-templates select="@*|node()"/> 43 </h1> 44 </xsl:template> 45 46 <xsl:template match="@*|node()"> 47 <xsl:copy> 48 <xsl:apply-templates select="@*|node()"/> 49 </xsl:copy> 50 </xsl:template> 51 52 </xsl:stylesheet>
Cette feuille de style devrait être très simple à comprendre si vous avez lu l'article sur la création du site web. Il y a cependant ligne 16 une requête XPath intéressante qui permet de ne récupérer que les $nb_news dernières nouvelles postées. Cela est expliqué plus en détail dans l'article sur XPath.
Il y a aussi de remarquable le modèle ligne 32 qui est somme toute très simple à comprendre, mais qui montre bien avec celui ligne 40 que XSLT ne se limite pas aux balises XHTML même si l'on s'est limité à ces balises dans l'article sur la création du site web. Quant à l'attribut mode, nous l'avions déjà rencontré dans l'autre article, nous le retrouvons ici aussi.
Le reste de la feuille de style est similaire aux feuilles de styles déjà utilisées dans l'autre article, et je n'y reviens donc pas.
La feuille de style précédente ne prend pas en compte le format de la date. Et elle élimine aussi les langues autres que l'anglais (à moins de spécifier en paramètre que lang=fr par exemple). Voici comment faire: l'idée est de conserver tous les tags <span<, et de les créer pour la date, pour toutes les langues du document. Vous devez ajouter la variables suivantes, par exemple au début, vers la ligne 11 de la feuille de style précédente:
1 <xsl:variable name="langs" 2 select="//span[not(@xml:lang=preceding::span/@xml:lang)]/@xml:lang"/>
Et ensuite, recopiez à la place du modèle mode='date' ceux qui suivent:
1 <xsl:template match="@*|node()" mode="date"> 2 <xsl:variable name="year" select="year/node()"/> 3 <xsl:variable name="month" select="month/node()"/> 4 <xsl:variable name="day" select="day/node()"/> 5 <xsl:for-each select="$langs"> 6 <xsl:variable name="l1" select="."/> 7 <xsl:choose> 8 <xsl:when test="$l1 = 'en'"> 9 <span xml:lang='{$l1}'> 10 <xsl:value-of select="$day"/> 11 <xsl:text>/</xsl:text> 12 <xsl:value-of select="$month"/> 13 <xsl:text>/</xsl:text> 14 <xsl:value-of select="$year"/> 15 </span> 16 </xsl:when> 17 <xsl:otherwise> 18 <span xml:lang='{$l1}'> 19 <xsl:value-of select="$month"/> 20 <xsl:text>/</xsl:text> 21 <xsl:value-of select="$day"/> 22 <xsl:text>/</xsl:text> 23 <xsl:value-of select="$year"/> 24 </span> 25 </xsl:otherwise> 26 </xsl:choose> 27 </xsl:for-each> 28 </xsl:template>
Supprimez enfin les deux modèles qui traitent des langues, lignes 46 à 51.
Comment récupérer la liste des langues du fichier, et surtout comment avoir une liste avec aucun duplicata ? Ceci n'est pas une mince affaire et mérite une explication. Tout se joue sur les deux lignes qui définissent la variable $langs. Sans entrer dans la syntaxe XPath qui fait l'objet de l'article du même nom, décomposons-la. Hors des crochets, on recherche tous les attributs xml:lang des noeuds span. Mais parmi les noeuds span, nous n'en selectionnons qu'une partie. En effet, lorsque l'égalité @xml:lang=preceding::span/@xml:lang est vraie, cela veut dire que le noeud span a un attribut xml:lang que l'on a déjà rencontré. Donc inutile de selectionné un tel noeud, et c'est pour cela qu'on ne prend que les noeuds pour lesquels l'égalite n'est pas vraie. C'est aussi simple que cela, mais même si on s'y connaît déjà un peu avec XSLT, on n'y pense pas forcément.
Ensuite, pour chaque noeud dont le mode est date, donc typiquement chaque noeud de date, nous mettons l'année, le mois et le jour dans des variables lignes 2 à 4. Cela simplifie la compréhension de la suite. Puis pour toutes les langues du document, ligne 5, nous effectuons un test ligne 8 pour savoir si cette langue doit être affichée en MMDDYYYY (lignes 9 à 15) ou comme nous en avons l'habitude DDMMYYYY (lignes 19 à 24). Cela nous permet de faire autant de lignes <span lang="XX"> qu'il y a de langues représentées dans le document XML. En effet, si dans l'autre article, celui qui explique comment générer des pages web pour chaque langue, nous n'avons besoin que d'une langue par page web, ici, c'est le contraire: nous devons être exhaustif.
Lignes 9 et 18, nous avons quelque chose de très intéressant, dans la valeur de l'attribut xml:lang
. Nous avons une variable à l'intérieur d'accolades. En fait, lorsque nous avons une valeur d'attribut, nous pouvons mettre entre accolades une expression à évaluer, si l'attribut doit effectivement faire partir du résultat. Cela nous convient tout à fait pour évaluer notre variable.
© 2003 Yves Mettier