Variables XSLT 1.0

erwan amoureux

Création, appel, et comportement d'une variable xslt.

- Titre : Variables XSLT 1.0

- Auteur : erwan amoureux

- Parution : 10 novembre 2006

- Mise à jour : 12 juillet 2020

- Licence : Copyright ® 2006 Erwan Amoureux. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. variable xslt

- I-A. Déclarations des variables

- I-B. Portée de la variable

- I-C. Contenue d'une variable

I - variable xslt

I-A - Déclarations des variables

fichier xml de référence

<?xml version="1.0" encoding="UTF-8"?>
<racine>
<valeur>1</valeur>
<valeur>2</valeur>
</racine>

Pour la suite des exemples de ce paragraphe, nous prendrons ce xml comme références. Le terme de « variable » peut être trompeur ; en effet la variable xslt

<xsl:variable name= ""/>

voit sa valeur fixée dès son initialisation, celle-ci se faisant soit par l'attribut select contenant un xpath, soit par des valeurs entre les balises. Etc.

exemples

<xsl:variable name= "var1" select="/A"/>
<xsl:variable name= "var2 ">ceci</xsl:variable>
<xsl:variable name= "var3"><xsl:value-of select= " ."/></xsl:variable>

Une fois ces balises écrites, le contenu ne pourra plus être modifié et sera appelé par l'attribut name de la balise concernée, précédée du signe $

exemple

<xsl:value-of select="$var2"/>

Attention si on ne peut modifier sa valeur, rien n'interdit de créer une nouvelle variable de même nom dans un autre nœud. Voir la fin du paragraphe suivant.

I-B - Portée de la variable

La portée d'une variable xslt est intimement liée à la structure xml du xslt, en effet elle correspond exactement au nœud dans lequel elle est déclarée et à tous les descendants de ce nœud. Ici des exemples seront certainement plus parlant ainsi

<?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" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="var1">a</xsl:variable>
<xsl:template match="/">
<xsl:variable name="var2">b</xsl:variable>
<html>
<body>

appel premier template
<br/>
<xsl:value-of select="$var1"/>
<br/>
<xsl:value-of select="$var2"/>
<br/>
<xsl:apply-templates select="//valeur"></xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="valeur">
<xsl:variable name="var3">c</xsl:variable>
appel deuxième template
<br/>
<xsl:value-of select="$var1"/>
<br/>
<xsl:value-of select="$var2"/>
<br/>
<xsl:value-of select="$var3"/>
<br/>
</xsl:template>
</xsl:stylesheet>

xsl:template match=« / » provoquera une erreur de du processeur xslt, sur la ligne soulignée. En effet, la variable var2 est déclarée dans la première template, mais comme la secondexsl:template match=« valeur » n'appartient pas à ses descendants elle y est inconnue. Par contre, après suppression de la ligne en erreur, on s'apercevra que var1 qui est déclarée dans la balise racinexsl:stylesheet version=« 1.0 » xmlns:xsl=« http://www.w3.org/1999/XSL/Transform » du document sera, elle, reconnue dans toute la feuille xslt.

Le résultat:

<html>
<body>

appel première template
<br/>a<br/>b<br/>
appel deuxième template
<br/>a<br/>c<br/>
appel deuxième template
<b/r>a<br/>c<b/r>
</body>
</html>

Attention ce qui est dit ici pour les templates est vrai pour tous les nœuds.

Exemple:

<xsl:if test="current()">
<xsl:variable name="var4" select="."/>
<xsl:value-of select="$var4"/>
</xsl:if>

fonctionnera, alors que :

<xsl:if test="current()">
<xsl:variable name="var4" select="."/>
</xsl:if>
<xsl:value-of select="$var4"/>

produira une erreur ;var4 disparaissant à la sortie du nœud xsl:if test=« current() ».

Note : le code ci-dessous est tout à fait valable :

<?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" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="var1" select="//valeur[2]"></xsl:variable>
<xsl:template match="/">
<html>
<body>
<xsl:variable name="var1" select="$var1+10"></xsl:variable>

<xsl:value-of select="$var1"/>
<br/>
<xsl:apply-templates select="//valeur"></xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="valeur">

<xsl:value-of select="$var1"/>
<br/>
</xsl:template>
</xsl:stylesheet>

En effet, on crée ici une variable locale au nœud xsl:template match=« / », qui prend le pas sur la précédente. Ce sont donc deux variables différentes, et non pas la modification de la première. D'ailleurs le résultat est :

<html>
<body>12<br/>2<br/>2<br/></body>
</html>

La valeur de la variable n'a pas été modifiée, une variable « locale » a simplement pris temporairement le pas sur la « globale ».

I-C - Contenue d'une variable

une variable peut contenir ces différents types de données: string, number, boolean, node-set qui appartiennent tous à Xpath ,plus le type node-fragment qui lui est particulier.

number

<xsl:variable name="var1" select="number(10.2)"/>
<xsl:variable name="var2" >15.2</xsl:variable>

string

<xsl:variable name="var3" >truc</xsl:variable>
<xsl:variable name="var4"  select="string('truc')"/>

booleen

<xsl:variable name="var5" select="$var1 < $var2"/>

Une autre façon de déclarer des string ou des number que vous pouvez avoir vu

<xsl:variable name="var2" >15.2</xsl:variable>
<xsl:variable name="var3" >truc</xsl:variable>

attention ce type d'écriture s’il est sans conséquence pour l'affichage peut entraîner des erreurs de tests. Ceci sera plus détaillé à la fin des node-fragment

fichier xslt

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="var1" select="number(10.2)"/>

<xsl:variable name="var2" >15.2</xsl:variable>

<xsl:variable name="var3" >truc</xsl:variable>

<xsl:variable name="var4" select="string('truc')"/>

<xsl:variable name="var5" select="$var1 < $var2"/>

<xsl:template match="/">

<html>

<body>

<xsl:value-of select="$var1"/>

<br/>

<xsl:value-of select="$var2"/>

<br/>

<xsl:value-of select="$var3"/>

<br/>

<xsl:value-of select="$var4"/>

<br/>

<xsl:value-of select="$var5"/>

<br/>

</body>

</html>

</xsl:template>

</xsl:stylesheet>

résultat

<html>

<body>10.2<br>15.2<br>truc<br>truc<br>true<br></body>

</html>

Pour les types node-set, il faut noter qu'un de leurs grands avantages est de pouvoir être utilisés dans des expressions xpath par exemple :

<xsl:variable name="var1" select="/racine"/>

<xsl:variable name="var2" select="//valeur"/>

$var2[1] permettra d'accéder à la première balise valeur, mais $var1/valeur[1] aussi. Toutes les expressions xpath sont utilisables sur une variable et une variable peut être aussi utilisée dans une expression.

fichier xslt

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="var1" select="/racine"/>

<xsl:variable name="var2" select="//valeur"/>

<xsl:template match="/">

<html>

<body>

<xsl:value-of select="$var2[1]"/>

<br></br>

<xsl:value-of select="$var1/valeur[1]"/>

<br></br>

<xsl:if test="$var1/valeur[1]=$var2[1]">

les deux expressions ont la même valeur.

</xsl:if>

</body>

</html>

</xsl:template>

</xsl:stylesheet>

résultat

<html>

<body>1<br>1<br>

les deux expressions ont la même valeur.

</body>

</html>

Enfin le dernier type qui est propre a la variable le node fragment. Le but est de (re-)créer des nœuds xml dans la variable et non le xpath (surtout si ceux-ci n'existent pas) exemple :

<xsl:variable name="var" >

<truc>

premier truc

</truc>

<truc>

second truc

</truc>

</xsl:variable>

attention, aucun xpath ne peut être utilise sur un node fragment, les [] et / sont interdits, et seuls les opérateurs sur les chaînes de caractères sont autorisés (length(),substring…). Un value of select de ce type de variable ne rendra comme résultat que le contenu des balises, pas les balises elles-mêmes :

fichier xslt

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="var" >

<racine>

<truc>

premier truc

</truc>

<truc>

second truc

</truc>

</racine>

</xsl:variable>

<xsl:template match="/">

<html>

<body>

<xsl:value-of select="$var"/>

</body>

</html>

</xsl:template>

</xsl:stylesheet>

résultat

<html>

<body>

premier truc

second truc

</body>

</html>

L'intérêt de ce type de variable se trouve plutôt dans la construction d'arbre xml, chapitre que nous verrons ultérieurement. Notons simplement que le xsl:copy-of prend lui en compte la présence des balises :

fichier xslt

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="var" >

<racine>

<truc>

premier truc

</truc>

<truc>

second truc

</truc>

</racine>

</xsl:variable>

<xsl:template match="/">

<xsl:copy-of select="$var">

</xsl:copy-of>

</xsl:template>

</xsl:stylesheet>

résultat

<?xml version="1.0" encoding="UTF-8"?>

<racine>

<truc>

premier truc

</truc>

<truc>

second truc

</truc>

</racine>

Note : attention de ne pas abuser de ce type d'écriture si l'on ne veut pas créer un node fragment. En effet cela peut perturber le processeur dans des tests,comme suit :

fichier xslt

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="var" >
2
</xsl:variable>

<xsl:template match="/">
<html>
<body>
<xsl:value-of select="racine/valeur[$var]">
</body>
</html

</xsl:template>

</xsl:stylesheet>

résultat

<html>
<body>
1
</body>
</html

En effet, ici $var n'est pas interprété comme un nombre.Si vous désirez gardez cette écriture de variable alors il vous faudra :

<xsl:value-of select="racine/valeur[position()=$var]">

ou

<xsl:value-of select="racine/valeur[number($var)]">

Pour finir, il est tout à fait possible, de faire appel par des apply-templates ou des call-templates (détail ultérieurement) à l'intérieur d'une variable. Le seul type de résultat inaccessible dans ce cas étant le node-set.

fichier xslt

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="var">

<xsl:apply-templates select="//valeur"/>

</xsl:variable>

<xsl:template match="/">

<html>

<body>

<xsl:value-of select="$var"/>

</body>

</html>

</xsl:template>

<xsl:template match="valeur">

<xsl:value-of select="concat(.,';')"/>

</xsl:template>

</xsl:stylesheet

résultat

<html>

<body>1;2;</body>

</html>