Accueil

Exemples XSLT

Afficher plein écran
 
Emmanuel Lazinier
Création de la page : 2000-11-10

Transcoder un fichier (XSLT 1.1)

Le fichier suivant comporte un certain nombre de caractères transcodés qu'il convient de restituer à leur valeur originelle, selon le tableau suivant :
 
Valeur actuelle
Valeur à restituer
%2C .
%E9 é
+ (espace)
 
 <?xml version="1.0" encoding="ISO-8859-1"?>
<commande>
   <articles>
      <article>
         <ref>DCRTRV620</ref>
         <quantite>1</quantite>
         <garantie monnaie="USD">210%2C00</garantie>
      </article>
      <article>
         <ref>139904</ref>
         <quantite>1</quantite>
         <garantie monnaie="FF">98%2C67</garantie>
      </article>
   </articles>
   <Nom>Dupont</Nom>
   <Prenom>Andr%E9-L%E9on</Prenom>
   <adresse>10+chemin+des+Pr%E9s-Carr%E9s</adresse>
   <Code_Postal>77300</Code_Postal>
   <ville>Br%E9tigny</ville>
   <email>James@positoile.com</email>
   <telephone>0165487892</telephone>
   <action>Envoyer</action>
</commande>
Notre feuille de transformation XSLT s'inspire de l'exemple de transformation de fichier CSV précédemment publié sur notre site.

La première partie de notre feuille de transformation XSLT va consister en déclaration, sous la forme d'un paramètre, de la table de transcodage:

<xsl:param name="transcodage">
<!-- Table de transcodage (ce pourrait être un fichier externe)-->
<item avant="%E9" apres="é"/>
<item avant="%2C" apres="."/>
<item avant="+" apres=" "/>
</xsl:param>
 
Chaque élément ("item") de ce fragment XML déclare un transcodage élémentaire à effectuer. L'attribut "avant" déclare une chaîne de caractères à transcoder et l'attribut après le résultat attendu du transcodage de cette chaîne.
Note. Aux termes de la spécification XSLT 1.0, le paramètre transcodage tel que déclaré ici est un fragment XML et n'est pas considéré comme constituant du XML bien formé. A ce titre il est aujourd'hui illégal de naviguer, comme nous allons le faire, à l'aide d'expressions XPath à l'intérieur de ce fragment. Nous l'avons fait néanmoins parce que :
  1. Il se trouve que le parseur MSXML 3.0, que nous avons utilisé permet depuis sa version de septembre 2000 de contourner cette interdiction par l'utilisation de la fonction d'extension propriétaire msxsl:node-set(). Voir la Feuille de transformation XSLT modifiée en conséquence
  2. Il est très probable que cette illégalité disparaîtra dès la version 1.1 de XSLT. Voir XSL Transformations Requirements Version 1.1
Voir aussi  Getting Value from XSL Parameters, par Kurt Cagle.
 
Viennent ensuite les templates qui sont au nombre de quatre.

Un premier template va reproduire à l'identique tous les noeuds (éléments et attributs) du fichier source. Un deuxième template va capturer spécifiquement les noeuds textuels du fichier source, passer en mode "transcode" et donner le contrôle au template de transcodage en lui passant en paramètre le noeud textuel.
 

<!-- Reproduire le document à l'identique -->
<xsl:template match="@* | *">
<xsl:copy>
<xsl:apply-templates select="@* | * | text()"/>
</xsl:copy>
</xsl:template>

<!-- ...Sauf les textes, que l'on va transcoder -->
<xsl:template match="text()">
<xsl:apply-templates select="msxsl:node-set($transcodage)/*[position()=1]" mode="transcode">
<xsl:with-param name="avanttranscodage" select="." />
</xsl:apply-templates>
</xsl:template>
 

Notre template de transcodage, lui, va naviguer sur la table de transcodage. Il va la parcourir élément ("item") par élément et à chaque fois passer la main au template nommé "substitue" (équivalent d'une fonction dans un langage de programmation traditionnel). Ce template va renvoyer, dans la variable 'aprestranscodage" le résultat de la substitution correspondante. Et ainsi de suite jusqu'à ce qu'il n'y ait plus d'élément dans la table de transcodage. Le résultat final sera alors renvoyé au template appelant qui va le substituer au noeud textuel initial.
<xsl:template match="*" mode="transcode">
<!-- template de transcodage. Navigue sur la table de transcodage -->
<xsl:param name="avanttranscodage"/>

<xsl:variable name="aprestranscodage">
<xsl:call-template name="substitue">
<xsl:with-param name="atranscoder" select="$avanttranscodage"/>
</xsl:call-template>
</xsl:variable>

<xsl:choose>
<xsl:when test="following-sibling::*">
<!-- Tant qu'il y a d'autres éléments dans la table de transcodage, relancer le même template sur ces éléments -->
<xsl:apply-templates select="following-sibling::*[position()=1]" mode="transcode">
<xsl:with-param name="avanttranscodage" select="$aprestranscodage"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<!-- Sinon, renvoyer le résultat du transcodage -->
<xsl:value-of select="$aprestranscodage"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
 

Le dernier template est donc un template nommé "substitue". Il substitue une chaîne précise à une autre chaîne précise (puisqu'il est positionné sur un élément précis de la table de transcodage). Il le fait au coup par coup, en se rappelant lui-même tant qu'il reste des substitutions de même type à faire. Quand il n'en reste plus il renvoie le résultat de ces transcodages successifs au template appelant.
<xsl:template name="substitue">
<!-- template récursif de susbstitution -->
<xsl:param name="atranscoder"/>

<xsl:choose>
<xsl:when test="contains($atranscoder,@avant)">
<!-- Si il reste qqch à transcoder, le transcoder -->
<xsl:variable name="resultat">
<xsl:value-of select="concat(substring-before($atranscoder,@avant),@apres, substring-after($atranscoder,@avant))"/>
</xsl:variable>
<xsl:call-template name="substitue">
<!-- Relancer le même template sur le résultat pour continuer le transcodage, s'il y a lieu -->
<xsl:with-param name="atranscoder" select="$resultat"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- Si plus rien à transcoder, ne rien faire et renvoyer le paramètre "à transcoder" -->
<xsl:value-of select="$atranscoder"/>
</xsl:otherwise>
</xsl:choose>

</xsl:template>

 
Voir/Télécharger les fichiers de l'exemple :


Contribuez ! Faites-nous profiter de vos exemples les plus significatifs.

Retour à la page d'accueil.