Travaux pratiques XSLT

Ces travaux pratiques sont découpés en dix-sept parties. Chaque partie crée un document HTML plus sophistiqué que la précédente en utilisant des éléments XSLT.

Utilisation de Xalan

Pour ces travaux pratiques, vous allez utiliser Xalan (version Java). Pour cela, vous pouvez utiliser le script shell run-xalan qu'il vous suffit de recopier chez vous et de rendre exécutable. Ce script est également sous le compte de l'utilisateur silber, vous pouvez donc le recopier chez vous par la commande Unix: cp ~silber/run-xalan votre_repertoire

La syntaxe est la suivante:

run-xalan fichier-xml fichier-xsl fichier-resultat

Voici le contenu de ce script:

#!/bin/bash
CLASSPATH=~silber/classes/xalan.jar:~silber/classes/xerces.jar
java -classpath $CLASSPATH org.apache.xalan.xslt.Process  -IN $1 -XSL $2 -OUT $3
      

Comme vous pouvez le voir, ce script appelle juste la JVM avec un chemin correct pour aller cherche des fichier JAR contenant Xalan (le processeur XSLT) et Xerces (le parseur XML implémentant DOM et SAX).

Processeur XSLT des navigateurs Web

Si vous ne voulez pas utiliser Xalan, vous pouvez effectuer des transformations XSLT avec votre navigateur web. Pour cela, rajoutez la ligne suivante sur la deuxieme ligne de votre fichier XML:

<?xml-stylesheet href="votrefichier.xsl" type="text/xsl"?>

La transformation s'effectuera quand vous chargez le fichier XML dans votre navigateur.

Documentation

Pour réaliser ces TP, vous pouvez utiliser la documentation courte de XML et de XSLT ou les documentations officielles qui se trouvent sur le site du W3C.

Un tutoriel en ligne très bien fait sur XSLT se trouve ici. Un autre sur XPath . Vous pouvez commencer le TP et revenir à ces tutoriels si vous êtes bloqué, où commencer par ces tutoriels avant de commencer le TP.

Première partie (avec la solution)

En partant du document XML juicers.xml (une liste de presse-fruits) et de sa DTD associée juicers.dtd, le but de cette première partie est de créer un document HTML contenant une liste des presse-fruits, identique au document juicers-list.html (Note: pour voir le source du document HTML à obtenir, vous pouvez utiliser le bouton droit de votre souris sur la page HTML dans votre navigateur et sélectionner 'View Page Source'). Pour cela, vous écrirez un fichier de transformation XSL juicers-list.xsl (ce premier exercice est corrigé, donc la solution est disponible. Dans la suite, c'est vous qui devrez écrire le script XSLT).

Pour obtenir le fichier résultat juicers-list.html, voici donc la commande que vous devrez utiliser:

run-xalan juicers.xml juicers-list.xsl juicers-list.html

Il est à noter qu'une exécution correcte de la commande ne renvoie aucun message.

Voici le contenu du fichier juicers-list.xsl:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">
  <xsl:output method="html"/>
  <xsl:template match="/">
    <HTML>
      <HEAD><TITLE>Juicers List</TITLE></HEAD>
      <BODY>
        <UL>
          <xsl:for-each select="/juicers/juicer">
            <LI><xsl:value-of select="name"/></LI>
          </xsl:for-each>
        </UL>
      </BODY>
    </HTML>
  </xsl:template>
</xsl:stylesheet>

Deuxième partie

Créez maintenant un document juicers-table.html à l'aide d'un fichier juicers-table.xsl.

Troisième partie

Créez une table avec le coût de chaque presse-fruit sur le modele de juicers-cost-table.html à l'aide d'un fichier juicers-cost-table.xsl.

Quatrième partie

Créez un document HTML juicers-cost-description.html avec deux table, une avec le nom du presse-fruit et son coût, une autre avec la description du presse-fruit (juicers-cost-description.xsl).

Cinquième partie

Créez un document HTML hyperlinked-cost-description-tables.html reprenant celui de la quatrième partie mais avec des liens entre un presse-fruit dans la première table et ce même presse-fruit dans la seconde (hyperlinked-cost-description-tables.xsl).

Pour faire cette exercice, vous aurez besoin de la notation {expression-xpath} qui permet de récupérer une valeur depuis le document XML (comme la fonction XSL <xsl:value-of select="...">) dans des guillemets. Par exemple:

<a href="{@id}-COST"/>

{@id} renvoie le meme resultat que la commande XSLT <xsl:value-of select="@id"/>

Sixième partie

Même chose que pour la cinquième partie mais en rajoutant des images pour chaque presse-fruit (hyperlinked-tables-with-images.html, hyperlinked-tables-with-images.xsl)

Septième partie

Écrivez un script XSL permettant de générer une page HTML affichant le coût moyen d'un presse-fruit. Voilà à quoi doit ressembler votre résultat:

Total number of juicers = 6
Cost of all juicers = 1696.93
The average cost of the juicers = $282.82 

Vous pouvez utiliser l'instruction XSLT <xsl:variable name="x" select="..."/;> pour déclarer des variables dans votre script. La récupération d'une valeur préalablement stockée dans une variable se fait en rajoutant un signe $ devant le nom de cette variable dans une expression XPath.

Pour faire cet exercice, vous devrez utiliser les fonction XPath count() et sum(). Pour formater un nombre de telle façon a ce qu'il ait deux chiffres après la virgule et un signe $ devant lui, utilisez la fonction XPath: format-number($avgCost, '$#.00'). Par exemple:

<xsl:value-of select="count(/juicers/juicer)"/>

donne le nombre d'éléments juicer dans le fichier XML.

Huitième partie

le but de cette partie est d'écrire un script getElectricJuicers.xsl permettant de générer un document HTML contenant une liste des presse-fruits qui sont électriques.

Le but de cet exercice est d'utiliser les variables XML et l'instruction xsl:if. Votre sortie doit ressembler à:

This juicer is electric: Champion Juicer
This juicer is electric: Green Power Gold Juice Extractor
This juicer is electric: Juiceman Jr.
This juicer is electric: Omega Juicer
This juicer is electric: Wheateena Wheatgrass Juicer

C'est-à-dire que pour chaque presse-fruits vous devez écrire "This juicer is electric:" suivi de son nom. Voici comment implémenter ceci:

Pour chaque presse-fruits
    - Récupérer son nom et le stocker dans une variable
    - Récupérer la valeur de l'élément/attribut indiquant si 
      il est électrique ou non et la stocker dans une variable
    - Tester la valeur de la variable "est_electrique" pour 
      déterminer si le presse-fruits est électrique. Si oui:
         - Afficher le texte "The juicer is electric:"
         - Afficher la valeur de la variable contenant le nom
         - Afficher un saut de ligne HMTL

Neuvième partie

Dans cette partie, il vous est demandé d'écrire un script XSLT (doesItContainThisJuicers.xsl) permettant de déterminer si la liste des presse-fruits contient les appareils Champion, Omega et Ultrex. Générez un fichier HTML avec le résultat de votre requête pour chaque appareil demandé.

Le but ici est d'utiliser les variables XSL et la fonction contains(). Vous allez créer une variable contenant la liste de tous les noms de presse-fruits (séparés par des ~) présents dans le document XML. Il faut ensuite déterminer si cette liste contient Champion, Omega et Ultrex.

Il vous est demandé d'afficher le contenu de la variable contenant la liste de tous les presse-fruits. Ensuite, voud devrez afficher une ligne pour chaque presse-fruits qui vous intéresse. Voici à quoi doit ressembler la sortie:

Juicer List: OJ Home Juicer~Champion Juicer~Green Power Gold Juice Extractor~Juiceman Jr.~Omega Juicer~Wheateena Wheatgrass Juicer
- contient Champion
- contient Omega
- ne contient pas Ultrex

Notez qu'il n'y a pas de ~ après le dernier presse-fruits.

L'instruction XSLT xsl:variable utilisée sous cette forme peut vous être utile:

<xsl:variable name="mavariable">
  ... contenu de la variable ...
</xsl:variable>

Dixième partie

Il y a plusieurs façon d'identifier un aéroport: par son code ICAO (par exemple BOS est le code ICAO pour Boston) ou encore par la latitude/longitude (par exemple 74.3N, 123.0W pour l'aéroport de Boston).

Voici le fichier airports.xml qui contient une liste d'aéroports.

Le contenu d'un élément location est une chaîne de caractères pouvant prendre deux formes: ICAO: code ou LatLon: valeur. Pour cet exercice vous allez créer un document HTML qui ressemblera à ceci (notez que vous devez convertir le caractères en majuscules):

ICAO = BOS
LatLon = 74.31W, 106.5N
ICAO = SLT
ICAO = MOL
Erreur! Les données doivent être: ICAO: code ou LatLon: valeur
LatLon = 43.01W, 116.8N

Onzième partie

Le prix des presse-fruits augmente régulièrement. Un document XML séparé (priceAdjuster.xml) est utilisé pour spécifier l'ajustement de prix devant être effectué sur un presse-fruit (cet exemple n'effectue pas d'ajustement). Le fichier priceAdjuster2.xml ne spécifie une modification de prix.

Vous devez dans cet exercice créer un document HTML contenant une table des presse-fruits (comme dans le tp 1). La différence est que le prix doit être ajusté en fonction du fichier priceAdjuster.xml. Lorsque vous aurez écrit votre script, testez-le avec priceAdjuster.xml etpriceAdjuster2.xml.

Aide : il existe une commande XPath (document()) permettant de lire un fichier externe. Cette commande peut-être utilisée de la façon suivante:

<xsl:variable name="priceAdjuster" select="document('priceAdjuster.xml')"/>

Une fois cette variable définie, elle peut être utilisée comme racine dans une expression XPath:

<xsl:if test="$priceAdjuster/priceAdjustment/adjustment/@action='no change'">
...
</xsl:if>

Douzième partie

En XSL, il est possible de créer des templates nommés acceptant des paramètres. Par exemple, voici un template appelé createJuicerCostTable qui a un paramètre sizeIncrease qui est positionné par défaut à 0:

<xsl:template name="createJuicerCostTable">
  <xsl:param name="sizeIncrease" select="0"/>
  ...
</xsl:template>

Une fois ce template défini, il est possible de l'appeler depuis un autre template avec les instructions XSL suivantes:

<xsl:call-template name="createJuicerCostTable">
   <xsl:with-param name="sizeIncrease" select="10"/>
</xsl:call-template>

Reprenez l'exercice précédent en écrivant le template nommé createJuicerCostTable qui va écrire le tableau HTML.

Treizième partie

Modifiez le script identity.xsl pour qu'il mette le nom des attributs et éléments de tout fichier XML en majuscules, sans modifier les données du fichier.

Quatorzième partie

Le fichier Classified.xml contient des données à transmettre mais certaines de ces données sont classées "top secret". Écrivez un script XSL qui produit un nouveau fichier XML où tout ce qui est classé "top secret" est absent.

Quinzième partie

Votre société de production de presse-fruits utilise en interne la DTD juicers.dtd. Le CFPF (Consortium des Fabricants de Presse-Fruits) s'est mis d'accord sur une représentation commune des catalogues de presse-fruits pour faciliter l'échange d'information. Voici à qui ressemble la nouvelle représentation: juicer-transformed.xml. Écrivez un script XSL qui permet de transformer votre représentation interne ( juicers.xml) en cette nouvelle représentation.

Seixième partie

Écrire un script XSL qui permet de récupérer tous les éléments PERSONAE ainsi que leurs sous-éléments du fichier AllsWellThatEndsWell.xml. Le fichier résultat doit ressembler à ceci:

<?xml version="1.0"?>
<PERSONAE>       
        <PERSONA>KING OF FRANCE</PERSONA>
        <PERSONA>DUKE OF FLORENCE</PERSONA>
        <PERSONA>BERTRAM, Count of Rousillon.</PERSONA>
        <PERSONA>LAFEU, an old lord.</PERSONA>
</PERSONAE>

Dix-septième partie

Écrire un script XSL qui permet d'obtenir le fichier juicers-new.xml. Vous devez utiliser l'attribut mode de l'élément xsl:template: vous devez utiliser deux patrons pour traiter l'élément juicer, un contenant juste le nom et un second contenant le nom, un / et le prix du presse-fruits.

Valid XHTML 1.0!W3C