Tutoriel XSLT F. Sajous ERSS – 01/04/2005
Plan XSLT Advanced Rappels XML XPath XSLT Principes Templates et moteur Structures de contrôle XSLT Advanced
Rappel superflu : XML Exemple : Morphalou <?xml version="1.0" encoding="iso-8859-1"?> <lexicalDatabase> <title level="resource">Morphalou : Lexique morphologique</title> <lexicalEntry lemma="linguistique" grammaticalCategory="commonNoun" grammaticalGender="feminine"> <inflectionGroup> <inflection orthography="linguistique" grammaticalNumber="singular"/> <inflection orthography="linguistiques" grammaticalNumber="plural"/> </inflectionGroup> </lexicalEntry> </lexicalDatabase> en-tête texte balise de début @ribut élément vide balise de fin
XPath : rappel... superflu ? langage pour adresser des parties de documents XML parties de documents = ensemble de noeuds de la structure arborescente sélection par type et la valeur des éléments type et la valeur des attributs place occupée dans l'arbre typologie des voisins, parents, descendants... fonctions XPath exemples //inflection[@orthography='linguistique']/@grammaticalNumber //inflection[@orthography='linguistique']/../../@grammaticalCategory //lexicalEntry[count(.//inflection[@orthography=../../@lemma]) = count(.//inflection)]
XSLT : acteurs XSL HTML XML source X PDF Texte ... Processeur XSLT comment quoi XML source X HTML PDF Texte ... à partir de quoi Processeur XSLT Processeur XSLT XML résultat sériali- sateur
Sélection + Transformation / règles de transformation XML filtrage (patrons ou templates) XML résultat
Et concrètement : les templates XML <?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> <xsl:template match="expression xpath1"> <!-- construire sortie correspondant à l'élément (aux éléments filtré(s) --> </xsl:template> <xsl:template match="expression xpath2"> <!-- construire sortie correspondant à l'élément (aux éléments) filtré(s) --> </xsl:stylesheet> en-tête racine patrons XML
Templates : un exemple XML source Résultat souhaité Résultat obtenu <analyse> <sent> <snum>1</snum> <token>Il</token> <token>était</token> <token>une</token> <token>fois</token> </sent> ... </analyse> Résultat souhaité <analyse> <sent> <taggertoken form="Il" pos="PRO"/> <taggertoken form="était" pos="VER:sg"/> <taggertoken form="une" pos="DET:femi:sg"/> <taggertoken form="fois" pos="NOM:femi:sg"/> ... </sent> <sent> ... </sent> </analyse> <xsl:template match="sent"> <sent><snum> <xsl:value-of select="position()"/></snum></sent> </xsl:template> <xsl:template match="taggertoken"> <token><xsl:value-of select="@form"/></token> XSL <sent> <snum>1</snum> </sent> ... Résultat obtenu
Moteur ! template correspondant ? Non ! Oui ! analyse sent sent ... taggertoken form="il" pos="PRO" taggertoken form="était" pos="VER:sg" taggertoken form="une" pos="DET:femi:sg" ... <xsl:template match="sent"> <snum><xsl:value-of select="position()"/></snum> </xsl:template> <xsl:template match="taggertoken"> ... <xsl:template match="sent"> ... </xsl:template> <xsl:template match="taggertoken"> ... <sent> <snum>1</snum> </sent>
Pour éviter les infanticides... XML source <sent> <snum>1</snum> <token>Il</token> <token>était</token> <token>une</token> <token>fois</token> </sent> ... Résultat <analyse> <sent> <taggertoken form="Il" pos="PRO"/> <taggertoken form="était" pos="VER:sg"/> <taggertoken form="une" pos="DET:femi:sg"/> <taggertoken form="fois" pos="NOM:femi:sg"/> ... </sent> ... </sent> </analyse> <analyse> </analyse> <xsl:template match="sent"> <sent><snum> <xsl:value-of select="position()"/></snum> <xsl:apply-templates/></sent> </xsl:template> <xsl:template match="taggertoken"> <token><xsl:value-of select="@form"/></token> <xsl:template match="/"> <analyse> <xsl:apply-templates/> </analyse> </xsl:template> ...et les parenticides ! XSL
Patrons par défaut réalisons un sommaire... Résultat <livre> <chapitre> <titre>XML</titre> <contenu>XML : un lang. de balises extensibles...</contenu> </chapitre> <chapitre> <titre>XSLT</titre> <contenu>XSLT est un lang. de tranforma°...</contenu> <chapitre/> </livre> <xsl:template match="titre"> <xsl:value-of select="position()"/> <xsl:value-of select="titre"/> </xsl:template> Résultat 1 XML XML : un lang. de balises extensibles.. 2 XSLT XSLT est un lang. de tranforma°... Le processeur XSLT pacourt l'arbre : - "en profondeur d'abord" (racine vers feuilles) - puis de gauche à droite Pour chaque élément rencontré : - patron défini : on l'applique - patron défini : patron par défaut !
Défaut des patrons 3 patrons par défaut : éléments textuels : générer le texte en sortie commentaires : ignorer autres noeuds : appliquer les patrons (définis ou par défaut) aux enfants <livre> <chapitre> <titre>XML</titre> <contenu>XML : un lang. de balises extensibles...</contenu> </chapitre> <chapitre> <titre>XSLT</titre> <contenu>XSLT est un lang. de tranforma°...</contenu> <chapitre/> </livre> <xsl:template match="titre"> <xsl:value-of select="position()"/> <xsl:value-of select="."/> </xsl:template> 1 XML XML : un lang. de balises extensibles... 2 XSLT XSLT est un lang. de tranforma°...
En attendant le grand soir... <livre> <chapitre> <titre>XML</titre> <contenu>XML : un lang. de balises extensibles...</contenu> </chapitre> <chapitre> <titre>XSLT</titre> <contenu>XSLT est un lang. de tranforma°...</contenu> <chapitre/> </livre> XML 1 XML 2 XSLT Résultat attendu <xsl:template match="titre"> <xsl:value-of select="position()"/> <xsl:value-of select="."/> </xsl:template> <xsl:template match="contenu"> </xsl:template> + template défini pour contenu qui génère une sortie vide <xsl:template match="/"> <xsl:for-each select="//titre"> <xsl:value-of select="position()"/> <xsl:value-of select="."/> </xsl:for-each> </xsl:template> ou template défini pour la racine et... structure de contrôle... <xsl:template match="*/text()"> </xsl:template> ou (joue sur les priorités)
Priorités du patronat... règle du "plus spécifique" <livre> <chapitre> <titre>XML</titre> <contenu>XML : un lang. de balises extensibles...</contenu> </chapitre> <chapitre> <titre>XSLT</titre> <contenu>XSLT est un lang. de tranforma°...</contenu> <chapitre/> </livre> <xsl:template match="titre"> <xsl:value-of select="position()"/> <xsl:value-of select="."/> </xsl:template> <xsl:template match="*/text()"> </xsl:template> règle du "plus spécifique" MAIS ! si on ajoute <xsl:template match="*"> </xsl:template> <xsl:template match="titre"> Titre : <xsl:value-of select="."/> </xsl:template> <xsl:template match="/*/*[position()=1]"> Pos1 : <xsl:value-of select="."/> </xsl:template> génère une sortie vide ? * et / "matchent" règle du "plus englobant" élément rencontré en 1er c'est toujours les plus gros patrons qui gagnent !
Priorités du patronat... ? <livre> <chapitre> <titre>XML</titre> <contenu>XML : un lang. de balises extensibles...</contenu> </chapitre> <chapitre> <titre>XSLT</titre> <contenu>XSLT est un lang. de tranforma°...</contenu> <chapitre/> </livre> <xsl:template match="titre"> <xsl:value-of select="position()"/> <xsl:value-of select="."/> </xsl:template> <xs:template match="*/text()"> </xsl:template> <xsl:template match="titre" priority="2"> Titre : <xsl:value-of select="."/> </xsl:template> <xsl:template match="/*/*[position()=1]" priority="1"> Pos1 : <xsl:value-of select="."/> </xsl:template> <xsl:template match="titre"> Titre : <xsl:value-of select="."/> </xsl:template> <xsl:template match="/*/*[position()=1]"> Pos1 : <xsl:value-of select="."/> </xsl:template> ?
Structures de contrôles <xsl:if test='fct xpath booléenne'> <!-- instr. si vrai --> </xsl:if> Conditionnelle Itération <xsl:for-each select="xpath1"> <xsl:sort select="xpath2" order="ascending | descending"/> <!-- instruction --> </xsl:for-each> pas de else ! <xsl:choose> <xsl:when test="cond1"> <!-- instr si con1 vraie --> </xsl:when> <xsl:when test="cond2"> <!-- instr si cond1 fausse et cond2 vraie --> <xsl:otherwise> <!-- instr si toutes les cond sont fausses --> </xsl:otherwise> </xsl:choose> Choix multiple (switch case default) ● xpath : absolu ou relatif à l'élément courant ● une liste de noeuds sélecionnés à chaque itération, un noeud devient l'élément courant ● instruction sort facultative mais non nécessairement unique
Action ! Lancer <oXygen/> 5.1 Fichiers XML et XSL dans C:\ERSS-XSLT Exercices/Session 1 Avant de partir, SVP : supprimer le répertoire C:\ERSS-XSLT désinstaller <oXygen/> (panneau de configuration, Ajout/Suppression de programmes)
En vrac... Quelques éléments pour aller plus loin
Variables <xsl:variable name="nom_var" [ instr XSLT dont le résultat deviendra la valeur de la variable] </xsl:variable> Une fois une variable définie, elle est constante !!! (i = i + 1 impossible) <xsl:value-of select='$nom_var'/> sortie HTML : <a href='{$nom_var}'>lien</a>
Créer des éléments XML <xsl:element name="nom élément"> <xsl:attribute name="nom_attr"> [ instructions XSLT ] </xsl:attribute> [ instructions XSLT ] </xsl:element>
Copier des éléments XML <xsl:copy> [ instructions XSLT ] </xsl:copy> Cette instruction ne copie que les balises ouvrantes et fermantes de l'élément courant (ne copie ni attributs, ni enfants) <xsl:copy> [ instructions XSLT ] <xsl:apply-templates/> </xsl:copy>
Copier des éléments XML (2) <xsl:copy-of select="XPath"> [ instructions XSLT ] </xsl:copy> copie toute la structure de l'élément sélectionné (y compris attributs et descendance) utilisation conjointe avec xsl:copy : <xsl:copy> <xsl:copy-of select="@*"/> [ instructions XSLT ] <xsl:apply-templates/> </xsl:copy>
Plusieurs documents XML Pour accéder à un docuement autre que celui en cours de transformation : document('cheminFichier')/XPath <xsl:value-of select="document('autre')/monElt[@id='63']"> XSL XML (autre) <...> ... <monElt id='63'> </monElt> XML source Résultat Processeur XSLT