Représentation et manipulation de données structurées
BE2 - Transformations XSLT
Florian CLERC - Gauthier CORNU
Note : Une version en ligne de notre travail est disponible en suivant ce lien. Le compte-rendu qui y est présent n'a rien de plus que cette version, si ce n'est que le lien associé au logo de validation du W3C est cette fois corretement renseigné, et permet d'avoir confirmation, directement sur le site du W3C, que le présent document est valide.
Introduction
Nous avions réalisé, lors du précédent BE, une première application XML afin de découvrir ses principaux mécanismes, et saisir sa facilité d'utilisation dans le domaine de la représentation des données. Cependant, lorsqu'il s'est agi de manipuler ces données en créant une feuille de style pour les présenter de manière agréable, nous avons très rapidement senti la nécessité d'un nouvel outil fin de remplir cette tâche. En effet, en utilisant simplement des feuilles de style de type CSS, nous étions vite limités par la structure immuable du document créé (une application XML permettant de gérer une bibliothèque doit répondre à certaines contraintes métier et de logique qui ne doivent en aucun cas être altérées sous prétexte d'en afficher le contenu...donc impossible d'utiliser certaines méthodes bie appréciées des designers html comme les div englobantes,...).
Ainsi, ce BE va employer une méthode tout à fait différente à travers des "feuilles de style" qui vont cette fois appliquer des transformations au document XML. On utilisera pour cela XSLT, une application XML. Un traitement préalable est donc apppliqué au document XML pour le transformer en un autre document XML bien formé, qui lui sera plus pratique à gérer pour l'affichage des données : il contiendra exactement les informations que l'on souhaite afficher (même les attributs), dans l'ordre que l'on souhaite, et avec une structure maîtrisée pour le design. La structure générée dans ce BE correspondra à chaque fois à un document au format XHTML1.0.
Plus concrètement, l'application XML que nous allons utiliser ici représente l'organisation des modules d'option d'une école, contenant des professeurs et des élèves (tous considérés de la même manière comme étant des "personne"), ainsi qu'un certain nombre de cours. Chaque cours a un professeur attitré et des élèves inscrits, dont on connaît les principales informations relatives à ce cours. A chaque fois, nous afficherons du mieux possible les données qui concernent cet environnement.
I. Première feuille de style : affichage de la liste des personnes
On débute avec une application simple qui ne va exploiter qu'une partie des données présentes dans notre application : celles qui concernent les personnes présentes dans l'application. Pour chacune d'entre elles, on dispose de leurs nom, prénom, adresse email, numéro de téléphone, adresse et ville. Chaque individu a également des attributes précisant sa civilité et son ID, mais nous ne les utilisons pas ici. Dès cette première application nous allons pouvoir réaliser une mise en forme qui aurait été (quasi-)impossible avec du CSS pur : disposer les informations sous forme d'un tableau.
Voici une description de la feuille de style XSLT, consultable en suivant ce lien, que nous avons réalisée afin d'arriver au résultat final :
- Le document que nous voulons au final générer doit être de type html, donc on donne la valeur "html" à l'attribut method pour l'élément xsl:output. A noter que, juste avant, 'xsl' est le préfixe que nous avons choisi pour le namespace de l'application XSLT.
- Le premier élément que l'on traite avec un élément xsl:template est la racine du document que l'on manipule, à savoir "option". C'est l'occasion de mettre en place la structure de base du document HTML, avec les balises html, head (qui permet d'ailleurs de lier une feuille de style CSS), body, et en insérant un titre. On appelle ensuite les autres templates récursivement.
- On indique très rapidement que l'on ne s'occupera ici pas des cours, et donc le template associé à cet élément est vide.
- Ensuite, on traite l'élément personnes en mettant en place la structure de base du tableau, avec notamment les noms de colonnes. L'étape de récursivité se trouve à l'intérieur de la balise tbody, c'est ici que l'on va insérer les lignes qui correspondent à chacune des personnes.
- Pour chaque personne, on ajoute une ligne qui sera contenue dans le tableau évoqué précédemment, et qui contient les informations de base souhaitées. Pour des informations simple comme le nom, prénom, numéro de téléphone ou encore adresse on se contente de recopier les informations (à un détail près que nous verrons juste après concernant le nom et la ville, pour lesquels nous effectuons un appel récursif supplémentaire à un template). Nous avons choisi ici d'afficher la ville dans le même champ que l'adresse, pour montrer une des manipulations de base possibles avec XSLT. Mettre l'adresse email sous forme de lien cliquable rend les choses un petit peu plus difficiles : on doit en effet passer par une création d'élément explicite, auquel on ajoute un attribut grâce à l'élément xsl:attribute.
- Enfin, nous appliquons un traitement très simple au nom de la personne et à celui de sa ville : on met toutes les lettres en majuscule. Ceci est très simple en utilisant la fonction XPath translate, appliquée au nom de l'élément courant (accessbile par '.'). A noter que l'utilisation du caractère '|' nous permet de définir cette transformation pour les deux éléments dans le même élément xsl:template.
- Une fois cette feuille de style créée, il ne faut pas oublier d'ajouter une instruction de traitement dans le document XML source, indiquant le chemin vers cette feuille de style.
La feuille de style CSS associée est très simple et se contente d'effectuer des traitements de base notamment pour afficher les bordures du tableau
Le résutat final est visible en suivant ce lien.
Le document qui est créé bien formé. Nous avons en effet pu le vérifier de deux manières :
- En récupérant le code source du document qui est au final obtenu grâce à la transformation, et en le faisant valider avec les outils proposés par le W3C (remarque : pour récupérer le code source on ne peut pas utiliser le traditionnel "ctrl+U", qui affiche ici uniquement le document XML initial, mais on peut récupérer le code html final en utilisant des outils comme firebug).
- En validant deux documents : le XML initial, ainsi que la feuille de style XSLT créée. Ces deux documents étant bien formés, alors le document obtenu est bien formé.
A noter que le document obtenu ne se contente pas d'être bien formé, il est également valide : il suit les standards du XHTML1.0
II. Transformations avancées : Résultats des élèves en cours
Nous allons maintenant réaliser deux feuilles de style XSLT un peu plus complexes, où nous allons utiliser les liens qui existent entre un cours et les personnes qui y participent, élèves et professeurs. Dans le document XML, cela se traduit par l'existence d'un ID pour chacune des personnes, et des références sont faites depuis les cours vers ces IDs.
II.1. Fiches de note des élèves
Le but est ici d'obtenir un document final qui permettra de visualiser, élève par élève, les cours auquel il participe ainsi que ses appréciations, notes et son nombre d'absences. Voici la manière dont nous avons procédé pour obtenir la feuille de style XSLT présente ici :
- Les premières étapes sont les mêmes que précédemment : on donne à xsl:output les mêmes valeurs d'attributs que précédemment, et le template de l'élément option permet de poser la structure de base du document. De même que précédemment le template utilisé pour les éléments cours est vide : on ne souhaite en effet pas classer de manière globale les informations affichées par cours, mais par élève. Enfin, on utilise le même template pour les éléments de type nom, afin de les passer en majuscules. On n'oublie pas non plus de mettre le bon lien vers cette feuille de style dans le document XML qui contient les données.
- Aucun template n'est créé pour l'élément personnes : il lui sera en effet appliqué un modèle implicite qui fera directement appel récursivement au template associé aux éléments personne.
- Il n'y a donc qu'un seul template réellement nouveau dans cette application : celui qui concerne les éléments personne. Parmi toutes les personnes, seules certaines d'entre elles nous intéressent : les élèves. Or il n'y a rien, à partir de ce que contient un élément personne, qui ne permette de savoir qui est élève : il est nécessaire de se reporter à la liste des cours pour avoir une liste des étudiants de chacun d'entre eux, référencé par leur ID. C'est pourquoi une variable est créée, dont le rôle est de tester si une personne est un élève. Concrètement, le test utilise une expression XPath qui sélectionne l'ensemble des éléments étudiant dont l'idref est égal à celui de l'élément courant (soit la personne dont on veut savoir si elle est étudiante ou non). Si la personne n'est élève d'aucun cours, alors l'expression XPath renvoyée sera vide, et le test sera donc négatif. Dans le cas contraire, la variable permettra non seulement d'obtenir un test positif, mais également de disposer de l'ensemble des éléments étudiant associés, où les informations que l'on souhaite afficher seront disponibles, et que l'on pourra parcourir facilement à l'aide de l'élément xsl:for-each. C'est donc à l'intérieur du xsl:if que se trouvent toutes les balises à afficher pour un élève. Il n'y a rien de particulier par rapport à l'exemple précédent (on génére un tableau contenant les informations), si ce n'est que l'on affiche maintenant le contenu d'un attribut, la civilité, ce qui est réalisé très simplement grâce à xsl:value-of. De même, afficher l'intitulé du cours concerné par certaines informations est très facile : il suffit d'emprunter un sens de parcours inverse dans l'arbre XML à partir d'un élément étudiant, et de récupérer l'attribut intitulé de son père.
On peut observer le résultat final de cette transformation à cette adresse. Cette fois encore le document généré est bien formé (on le vérifie de deux manières différentes), et valide XHTML1.0
II.2. Récapitulatifs de cours
On va maintenant créer une fiche pour chaque cours, qui nous permettre d'afficher les informations relatives à ce cours : son intitulé, le professeur responsable ainsi que les élèves y participant et leurs informations vis-à-vis de ce cours.
Voici la feuille XSLT réalisée, et quelques détails concernant sa réalisation :
- Cette fois encore la structure de base est posée dans le template de l'élément racine. De manière inverse à la feuille précédente, c'est le template de l'élément personnes qui sera vide, tandis que celui de cours va contenir une structure importante.
- On commence par le template correspondant à l'élément cours. Son principe est simple : il englobe toutes les informations concernant le cours dans un div, indiquant tout d'abord celles relatives au professeur, puis celles relatives aux élèves (sous forme d'un tableau dont on définit dans ce template la ligne d'en-tête). Nous avons à notre disposition pour le professeur un IDREF qui fait référence à une personne. On crée donc une variable dont la valeur est cet idref, puis on insère l'élément xsl:apply-templates qui concerne la personne ayant cet id (grâce à l'expression XPath "personne[@id=$idprof]". A noter que l'on ajoute un attribut mode ici : en effet, les professeurs ne sont pas les seules personnes que l'on voudra afficher, et il est nécessaire de pouvoir différencier le template les concernant de celui qui traitera les étudiants.
- Le template de personne en mode prof est très simple, et permet d'afficher les nom et prénom du professeur, ainsi que son adresse email (cliquable, ainsi que nous l'avons déjà fait lors de la première application).
- Le principe de traitement des éléments étudiant est sensiblement le même que celui qui concerne l'élément cours : on utilise l'idref qui est présent en attribut pour localiser dans l'arbre XML la personne correspondante, puis on affiche les informations qui nous intéressent grâce à un template qui concerne toujours les éléments personne, mais cette fois avec un mode "étudiant".
Le résultat de cette troisième feuille de style peut être visualisé ici. Ce document est à la fois bien formé et valide XHTML1.0
III. Génération d'un document SVG : représentation graphique des résultats
Dans cette partie, nous allons utiliser une feuille de style XSLT pour transformer notre document XML en un document SVG. Concrètement, nous allons créer une représentation graphique des résultats des différents élèves dans les deux cours. Nous allons donc dessiner les différents éléments de chaque histogramme, avec cette feuille dont nous détaillons le fonctionnement :
- Intitulé du cours : on commence par écrire l'intitulé du cours en haut à gauche.
- Noms des étudiants : on écrit le nom de chaque étudiant suivant ce cours. Les noms sont espacés de 100px (il pourrait donc y avoir recouvrement si un étudiant a un long nom).
- Axe des abscisses et des ordonnées : l'axe des abscisses est dessiné juste au-dessus des noms des étudiants. Sa longueur dépend donc du nombre d'étudiants dans le cours. L'axe des ordonnées est le même quel que soit le cours : il fixe la hauteur de l'histogramme. Les deux axes sont terminés par des flèches (décalage d'une coordonnée de 10px).
- Barres de l'histogramme : on dessine maintenant les barres représentant la note de chaque étudiant dans ce cours. Ces barres sont construites avec un rectangle commençant juste au-dessus de l'axe des abscisses et dont la hauteur est proportionnelle à la note. Des calculs sont nécessaires pour déterminer l'origine de chaque rectangle ainsi que sa hauteur : la hauteur maximale de chaque barre est de 250px et le haut de l'axe des abscisses se trouve à 279px; le rectangle doit donc commencer à l'ordonnée 279-(250*$note div 20) (où $note est la note de l'étudiant dans ce cours) et avoir une hauteur de 250*$note div 20. La largeur des rectangles est identique pour tous les rectangles.
- Au-dessus de chaque rectangle précédemment dessiné, on écrit la note de l'étudiant.
- Moyenne du cours : on dessine une ligne rouge sur l'histogramme représentant la moyenne des étudiants dans ce cours. On écrit également la valeur de cette moyenne au dessus du trait précédent à son extrémité droite.
Finalement, on a pu dessiner facilement un histogramme en SVG grâce à une feuille de transformation XSLT, le résultat peut être visualisé ici. Pourtant, cet histogramme n'est pas très esthétique il n'est possible de le styliser comme on pourrait le faire avec un document HTML et une feuille de style CSS. Toute modification stylistique demande donc une modification de la feuille XSLT. On pourrait imaginer construire d'autres représentations des notes des étudiants, en prenant par exemple comme origine non pas un cours mais un étudiant et étudier ses résultats dans les cours qu'il suit.
Conclusion
Après avoir réalisé différentes feuilles de style permettant de manipuler un document XML en vue de son affichage, il apparaît au final qu'aucune comparaison n'est possible entre l'utilisation de feuilles CSS seules et l'utilisations de documents XSLT pour la mise en forme de documents XML. Par exemple, l'utilisation d'éléments HTML de base tels que les tableaux nous a grandement facilité la tâche pour afficher certaines séries de données. Le développeur dispose d'une liberté totale pour générer la structure du document qu'il veut afficher, et il est ensuite beaucoup plus facile d'appliquer des propriétés CSS pour arriver à un résultat voulu. Par ailleurs, l'aspect générique du langage XML nous a également permet de réutiliser plusieurs "briques" de nos feuilles de transformation tout au long de ce BE.
Dans le cas de ce BE nous avons dupliqué pour des raisons pratiques le fichier source contenant les données pour lui associer à chaque fois une nouvelle feuille de style. Cette méthode serait bien entendu à proscrire dans le cas de fichiers plus importants en taille, et il faudrait alors utiliser l'appel à des entités externes (même si ces appels peuvent parfois poser problème avec certains navigateurs...).