Exemples XSLT |
Afficher plein écran |
Au préalable on aura transformé le fichier source en fichier
XML bien formé en l'encadrant par des balises <doc>
et </doc> et en ajoutant en tête
une processing instruction XML : <?xml version="1.0"?>
La première partie de notre feuille de transformation
XSLT va consister en déclaration de paramètres :
<!-- modèle du XML à obtenir -->
<xsl:param name="modele">
<doc>
<ligne separateur="
" repetable="oui"> <!-- séparateur
: retour ligne -->
<no-ligne separateur=" "/> <!-- séparateur
: 4 espaces -->
<data-1 separateur=" "/> <!-- séparateur : 1 espace
-->
<data-2 separateur=" "/> <!-- séparateur
: 3 espaces -->
<data-3/>
<data-4/>
<data-5/>
<data-6/>
<data-7/>
</ligne>
</doc>
</xsl:param>
Le deuxième paramètre (modele) est un fragment XML qui décrit la structure du fichier XML que l'on souhaite obtenir en sortie. Sur les éléments de ce fragment on a spécifié, chaque fois que nécessaire, sous forme d'attributs :
Un premier template va naviguer sur les éléments du fichier source. (Notre exemple n'en comporte qu'un mais notre feuille de style est d'usage général et pourrait fonctionner pour "sausissonner" un ou plusieur éléments à l'intérieur d'une page XML, ou XHTML, complexe)
Ce template va tester si l'élément du fichier source à le même nom qu'un élément du fragment modele. Si ce n'est pas le cas il va simplement reproduire l'élément. Si c'est le cas, par contre, il va en déduire qu'il s'agit d'un élément à saucisonner et il va, après avoir reproduit l'élément, passer en mode "saucisonne" et donner la main à notre deuxième template qui, lui, va naviguer sur le modèle et non plus sur le fichier source. Et à ce deuxième template il va transmettre en paramètre la chaîne de caractère à découper, autrement dit le contenu de l'élément. (dans notre exemple il s'agira du contenu de la balise <doc> donc de l'ensemble du fichier d'origine.)
<xsl:when test="$modele/*[name()=name(current())]">
<!-- si dans le modele il y a un élément de même
nom, on lance le saucissonnage de son contenu (passé en paramètre)
en naviguant sur le *modèle* -->
<xsl:apply-templates select="$modele/*[name()=name(current())]/*[position()=1]"
mode="saucissonne">
<xsl:with-param name="chaine" select="."/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<!-- si dans le modele il n'y a pas d'élément de même
nom, on recopie simplement -->
<xsl:apply-templates select="node()|@*"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
<xsl:param name="chaine"/>
<!-- détermine le séparateur à utiliser -->
<xsl:variable name="separateur">
<xsl:choose>
<xsl:when test="@separateur">
<xsl:value-of select="@separateur"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$separateurdefaut"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- détermine la rondelle à découper -->
<xsl:variable name="rondelle">
<xsl:choose>
<xsl:when test="contains($chaine, $separateur)">
<xsl:value-of select="substring-before($chaine, $separateur)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$chaine"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- détermine le reste du saucisson -->
<xsl:variable name="reste">
<xsl:value-of select="substring-after($chaine, $separateur)"/>
<!-- le reste est vide si pas de séparateur dans la chaîne
-->
</xsl:variable>
<xsl:copy>
<xsl:choose>
<xsl:when test="child::*">
<!-- si l'élément à des enfants, leur renvoyer
la balle -->
<xsl:apply-templates select="child::*[position()=1]" mode="saucissonne">
<xsl:with-param name="chaine" select="$rondelle"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<!-- si l'élément n'a pas d'enfant, y mettre la rondelle
-->
<xsl:value-of select="normalize-space($rondelle)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
<!-- relancer le processus de saucisonnage sur les éléments
suivants du modèle -->
<xsl:if test="string-length($reste) > 0"> <!-- ce test est facultatif
: il supprime d'éventuels éléments vides -->
<xsl:apply-templates select="following-sibling::*[position()=1]"
mode="saucissonne">
<xsl:with-param name="chaine" select="$reste"/>
</xsl:apply-templates>
</xsl:if>
<!-- si l'élément est répétable, relancer
sur le *même* élément -->
<xsl:if test="(@repetable='oui')and(string-length($reste) > 0)">
<!-- ici le test sur la longueur de chaîne restante est indispensable
pour arrêter la boucle -->
<xsl:apply-templates select="." mode="saucissonne">
<xsl:with-param name="chaine" select="$reste"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
Retour à la page d'accueil.