Cours XSLT/XPath - Yves Laborde XSLT : XML Stylesheet Language Transformation & XPath : langage d’adressage de parties de documents XML Une introduction à XSLT & Xpath pour l'analyse de documents XML Université Evry Val d'Essonne
XSLT : mise en pratique Note : pour apprendre ces techniques, il est indispensable de disposer d’un processeur XSLT et de tester et modifier les exemples du diaporama. Nous pourrions utiliser : SAX (Simple API for XML), DOM (Document Object Model) ou JDom : des librairies Java très complètes (et dont JDom est la plus simple d’emploi) Des applicatifs spécialisés ex: Cooktop 2.5 (freeware), Altova XMLSpy (shareware) et bien d’autres...
Feuille de style et transformation Cours XSLT/XPath - Yves Laborde Feuille de style et transformation (1) Le programme XSLT est appelé une « feuille de style » et contient des instructions de réécriture du document (2) La feuille de style accompagne un document XML lui-même fourni à un programme, appelé « processeur XSLT » (3) Le processeur « transforme » le document XML en fonction des instructions de réécriture contenu dans la feuille de style et produit en sortie un nouveau document (4). (1) Feuille de style XSLT (+Xpath) (3) Processeur XSLT (2) Document XML (4) Document transformé XML / HTML / texte / ... Université Evry Val d'Essonne
Un exemple : la fiche de description du film Vertigo <?xml version="1.0" encoding="ISO-8859-1"?> <FILM> <TITRE>Vertigo</TITRE> <IMAGE>Vertigo.gif</IMAGE> <AUTEUR>Alfred Hitchcock</AUTEUR> <ANNEE>1958</ANNEE> <GENRE>Drame</GENRE> <PAYS>Etats Unis</PAYS> <RESUME>Scottie Ferguson, ancien inspecteur de police, est sujet au vertige depuis qu'il a vu mourir son collègue. Elster, son ami, le charge de surveiller sa femme, Madeleine, ayant des tendances suicidaires. Amoureux de la jeune femme Scottie ne remarque pas le piège qui se trame autour de lui et dont il va être la victime... </RESUME> </FILM>
Un exemple de transformation HTML de la fiche de description du film Vertigo Document HTML produit Version HTML du document Vertigo.xml (affiché par Netscape) <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8 »> <title>Film: Vertigo</title </head> <body bgcolor="white »> <p><img SRC="Vertigo.gif" align="left" height="220"> <h1><i>Vertigo</i></h1>Drame, <i>Etats Unis</i>, 1958</p> <p>Mis en scène par <b>Alfred Hitchcock</b> <h3>Résumé</h3>Scottie Ferguson, ancien inspecteur de police, est sujet au vertige depuis qu’il a vu mourir son collègue. Elster, son ami, le charge de surveiller sa femme, Madeleine, ayant des tendances suicidaires. Amoureux de la jeune femme Scottie ne remarque pas le piège qui se trame autour de lui et dont il va être la victime... </p> </body> </html> Une mise en forme a été appliquée au cours de la transformation du document par un processeur XSLT. Les balises XML ont disparu au profit de balises HTML.
Cours XSLT/XPath - Yves Laborde Un exemple de transformation EXCEL de la fiche de description du film Vertigo Version EXCEL du document Alien.xml Titre Auteur Année Pays Genre Résumé Alien Ridley Scott 1979 USA Science-fiction Près d’un vaisseau spatial échoué sur une lointaine planète, des Terriens en mission découvrent de bien étranges "oeufs". . La transformation du document a produit un document EXCEL. Les balises XML ont disparu au profit de celles propres à EXCEL (non montrées ici). Université Evry Val d'Essonne
Principe de la transformation XSLT Cours XSLT/XPath - Yves Laborde Principe de la transformation XSLT La feuille de style décrit des règles de transformation que le processeur applique au document (quand, quoi et comment réécrire chaque partie du document) Pour cette transformation : On peut sélectionner des données dans le document source. Les requêtes peuvent utiliser les noms et ordre des balises, noms et valeurs des attributs, contenu du texte, position dans l’arborescence (contexte), etc. On peut également manipuler ces données (filtrer, trier, réarranger, décompter...) et aussi ajouter de nouveaux éléments. Université Evry Val d'Essonne
Transformation en un document HTML Pour produire un document HTML : on doit transformer l'arbre XML en un arbre HTML Feuille de style XSLT : règles de la transformation Arbre XML source Arbre HTML résultant root AAA BBB Text CCC html head body … Document HTML produit Document XML source Transformation Processeur XSLT
Exemples d’utilisation Cours XSLT/XPath - Yves Laborde Exemples d’utilisation Mettre en forme les information d'un document XML Connaissant à l'avance la structure logique du document Composer des sous-documents Créer une version sans les <RESUME> ou sans les <PRIX>… Quantifier Nombre de projection d'un <FILM> dans le mois... Convertir dans un format spécifique XML vers XML, Hyperbase, Unitexte, sans balise... ou vers des formats de lecture : (x)html, pdf, Word, Excel, Open Office, LaTex... Maintenir et enrichir un document Possibilité d’ajouter de l’information (ex: images, prix moyens...) Université Evry Val d'Essonne
Intérêt du couple XML/XSLT AVANTAGES : On ne maintient pas différentes versions du document pour les différents formats de sortie ou les différents sous-documents => maintenance On peut appliquer les mêmes feuilles de style à plusieurs documents => simplicité On se concentre soit sur les données du document soit sur ses représentation => modularité
Objectif du diaporama Introduction aux principes généraux des langages XSLT et Xpath Introduction à la réalisation des principales tâches : extraire des informations, calculer des valeurs globales, convertir et ajouter de l’information Montrer les deux approches possibles : l'approche procédurale l'approche par templates
Introduction aux principes généraux par l'approche procédurale
Cours XSLT/XPath - Yves Laborde Une première feuille de style Cette feuille de style récupère tout le texte d’un document XML <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding= "UTF-8" method="html" /> <xsl:template match="/"> <html> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8" /> <body> <xsl:value-of select="."> </body> </html> </xsl:template> </xsl:stylesheet> Balises préfixées par « xsl: » => instructions XSLT traitées par le processeur XSLT Balises non-préfixées par « xsl: » => Texte recopié littéralement en sortie Il constituera le document de sortie. Université Evry Val d'Essonne
Explications Le processeur lit la feuille, imprime ce qui est littéral (le texte ou les balises non préfixés par « xsl: ») et évalue/exécute les instructions préfixées par « xsl: » Ici les balises ajoutées sont en HTML : à partir du document on génère une page HTML. Le résultat de la transformation peut ainsi être affiché par un navigateur. Appliquée au document Vertigo.XML, cette feuille de style donne : <html> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8"> <body> Vertigo Vertigo.gif Alfred Hitchcock 1958 Drame Etats Unis Scottie Ferguson, ancien inspecteur de police, est sujet au vertige depuis qu'il a vu mourir son collègue. Elster, son ami, le charge de surveiller sa femme, Madeleine, ayant des tendances suicidaires. Amoureux de la jeune femme Scottie ne remarque pas le piège qui se trame autour de lui et dont il va être la victime... </body> </html>
Cours XSLT/XPath - Yves Laborde Pour résumer Une feuille de style est un document XML L'élément racine est xsl:stylesheet avec deux attributs obligatoires (version et xmlns:xsl) D'autres instructions peuvent apparaître, comme xsl:template ou xsl:value-of Tout ce qui est préfixé par « xsl:» est une instruction XSLT, qui est exécutée par le processeur et remplacée par son résultat. Tout ce qui n'est pas "préfixé" est reproduit littéralement Université Evry Val d'Essonne
Prenons un exemple plus complet : <?xml version="1.0" encoding="UTF-8"?> <CINEMA> <NOM>Epée de bois</NOM> <ADRESSE>100, rue Mouffetard</ADRESSE> <METRO>Censier-Daubenton</METRO> <SALLE NO='1' PLACES='320'> <TITRE>Alien</TITRE> <REMARQUE>Réservation conseillée</REMARQUE> <SEANCES> <SEANCE>15:00</SEANCE> <SEANCE>18:00</SEANCE> <SEANCE>21:00</SEANCE> </SEANCES> </SALLE> <SALLE NO='2' PLACES='120'> <TITRE>Vertigo</TITRE> <SEANCE>22:00</SEANCE> </CINEMA>
Extraire le texte contenu dans une balise Cours XSLT/XPath - Yves Laborde Extraire le texte contenu dans une balise <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding= "UTF-8" method="html" /> <xsl:template match="/"> <html> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8" /> <body> <p>Horaire de la première séance : <xsl:value-of select="/CINEMA/SALLE/SEANCES/SEANCE"/> </p> </body> </html> </xsl:template> </xsl:stylesheet> Université Evry Val d'Essonne
L'instruction xsl:value-of Cours XSLT/XPath - Yves Laborde L'instruction xsl:value-of <xsl:value-of select="/CINEMA/SALLE/.../SEANCE"/> Remplacer cette instruction par le texte du premier élément… … trouvé à cet endroit La valeur de l'attribut select est une expression XPath : elle désigne un endroit du document où aller chercher le texte. Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde <xsl:value-of select = "//SALLE/SEANCES/SEANCE"/> Il y a souvent beaucoup de <SEANCE> qui correspondent au chemin formulé L’expression XPath les retourne toutes, mais la fonction xsl:value-of ne sélectionne que la première et retourne son texte. ① ② ④ ③ L’arbre est toujours parcouru de haut en bas et de gauche à droite (i.e. dans l’ordre physique de déclaration des entités ①,②,③,④...). Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde XPath est une autre recommandation utilisée par XSLT ; c'est un langage. XPath remplit la fonction de « sélectionner », « pointer » sur des éléments d'un document XML, tandis que XSLT organise, trie, remplace... et finalement transforme. XPath retourne des nœuds de l'arborescence, par exemple des balises, des attributs, des commentaires. XPath parcours la structure logique des documents XML (racine, noms des balises et attributs, contexte actuel, ordre…) Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde xsl:value-of convertit le nœud en texte en supprimant les éventuelles balises incluses Soit le document XML : <p>du texte et <hi style="italics"> d'autres</hi> éléments</p> Soit l'instruction XSLT … <xsl:value-of select="p" /> L'expression XPath retourne tous les « nœud » <p>, XSLT prend le premier et le convertit en texte y compris ses fils : Du texte et d'autres éléments Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde xsl:for-each Si l'on veut traiter séparément tous les nœuds retournés par l'expression XPath, il faut utiliser xsl:for-each <xsl:for-each select= "...expression Xpath..."> ...traitement une à une les nœuds trouvés... </xsl:for-each> Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde xsl:for-each <xsl:for-each select="//SALLE/SEANCES/SEANCE"> <p><i><xsl:value-of select="." /></i></p> </xsl:for-each> 4 nœuds sont trouvés <p><i>15:00</i></p> <p><i>18:00</i></p> <p><i>21:00</i></p> <p><i>22:00</i></p> Université Evry Val d'Essonne
xsl:for-each xsl:for-each regroupe d’abord les nœuds avec select, ensuite exécute le contenu de la boucle autant de fois qu’il y a de nœuds L'expression XPath de select trouve quatre nœuds. S'il n'y avait aucun élément la boucle ne serait pas exécutée. À chaque passage on traite un des nœuds trouvés, qui devient le "nœud contexte" durant ce passage et qui peut être désigné par ".". Rq: Dans le contenu de la boucle, on peut se déplacer à nouveau dans l'arborescence, mettre un élément littéral, etc. ; il suffit d’utiliser une autre instruction XLS conjointement à une expression Xpath :
Cours XSLT/XPath - Yves Laborde xsl:for-each <xsl:for-each select= "//SALLE"> <xsl:for-each/> => trouve 2 nœuds ...select="./TITRE" => trouve 2 nœuds ...select="./SEANCES/SEANCE" => trouve 4 nœuds A chaque itération, les deux nouvelles expressions Xpath sont appliquées en partant du nœud contexte ".". Ce nœud est toujours une salle mais pas toujours la même. Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde xsl:for-each <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html><body> <p>Nom du cinéma: <xsl:value-of select = "//NOM"/> </p> <xsl:for-each select="//SALLE"> <p>Film à l’affiche : <xsl:value-of select= "./TITRE"/> <p>Première séance : <xsl:value-of select= "./SEANCES/SEANCE"/> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet> Université Evry Val d'Essonne
Le nœud contexte Il y a toujours un nœud contexte quand une instruction est exécutée. Ce nœud contexte peut être désigné explicitement avec "." select = "./SEANCES/SEANCE" C'est à partir du nœud contexte que sont évaluées les expressions XPath qui ne commencent ni par « / » ni par « // ». On aurait donc aussi bien pu écrire (mais cela est moins explicite) : select = "SEANCES/SEANCE" mais aussi : select = ".//SEANCE" qui va chercher tous les nœuds fils quelque soit leurs profondeurs à partir du nœud contexte
Imbrications de xsl:for-each Une utilisation de xsl:for-each serait de produire la table des matières d’un texte On ne sait pas combien il y aura de titres de niveau 1, de niveau 2, etc. Il faut traiter tous les titres de niveaux 1, puis dans chaque niveau 1, traiter les niveaux 2, etc. On devra donc imbriquer des boucles xsl:for-each
Une table des matières (1) Le livre a comme racine <BOOK> et son titre général du livre est donné dans une balise fille <TITLE>. Les chapitres du livre sont des balises <chap> possédant un attribut level indiquant leur niveau hiérarchique et ayant alors un élément fils <title> dont le texte est le titre. Par ailleurs, les niveaux sont imbriquées les uns dans les autres. <BOOK> <TITLE>LES LANGAGES XML</TITLE> <chap level="1"> <title>Le langage XML</title> ... <chap level="2"> <title>Les balises XML</title> ... </chap> <chap level="2"> <title>Les attributs XML</title> ... </chap> </chap> <chap level="1"> <title>Le langage XSLT</title> ... </chap> <chap level="2"> <title>L'nstruction template</title> ... </chap> <chap level="2"> <title>L'instruction value-of</title> ... </chap> ... </BOOK>
Prédicats pour les attributs des nœuds Cours XSLT/XPath - Yves Laborde Prédicats pour les attributs des nœuds select="chap[@level = '1']" Ce qui est entre crochets est un prédicat : il permet de filtrer les éléments sélectionnés. « @ » permet de désigner un attribut (raccourcis de « attribute:: »). ATTENTION: respecter l’alternance guillemets / apostrophes select="chap[@level='1']/title" Sélectionne les éléments title directement en dessous de chap dont l’attribut level vaut '1’ Université Evry Val d'Essonne
Une table des matières simple (2) <xsl:for-each select="/BOOK"> <p>Titre : <xsl:value-of select= "./TITLE"/></p> <xsl:for-each select="./chap[@level = '1']"> <h1><xsl:value-of select="./title"/></h1> <xsl:for-each select="./chap[@level = '2']"> <h2><xsl:value-of select="./title"/></h2> <xsl:for-each select="./chap[@level = '3']"> <h3><xsl:value-of select="./title"/></h3> </xsl:for-each> <hr/> L’expression Xpath commence par « . » : chap est recherché parmi les enfants des nœuds contextes trouvés (ici, un BOOK) Par rapport au nouveau contexte chap, on désigne les enfants title. Idem pour toutes les autres.
Cours XSLT/XPath - Yves Laborde Classer avec xsl:sort <xsl:for-each select="//SALLE"> <xsl:sort select = "TITRE" order = "ascending"/> <!-- les films sont classés par leur titre--> <!–- ils peuvent maintenant être traités--> <!-- les uns à la suite des autres--> <xsl:value-of select="...exp XPath..." /> </xsl:for-each> Les éléments sont extraits avec for-each ; mais avant d’être traités un à un, ils sont classés par xsl:sort – ici par ordre alphanumérique («ascending») – en fonction du contenu du select de sort. Ici les films sont donc classés par leurs titres. Université Evry Val d'Essonne
xsl:sort (syntaxe)
Ajouter un index : xsl:number xsl:number permet de retourner un nombre correspondant à l'index de l'élément dans le node set (l’ensemble des éléments retournés pas la précédente instruction Xpath => le contexte) . <xsl:for-each select="//SEANCE"> <xsl:number value = "./position()" format = "A. "/> <xsl:value-of select="." /> , </xsl:for-each> A. 15:00 , B. 18:00 , C. 21:00 , D. 22:00 Les positions sont traduites d'après le format de l’instruction number
xsl:output Indication du jeu de caractères de la sortie : encoding='...' Indication du type de sortie (text, xml, html...) : method='...' <xsl:stylesheet version="1.0" xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding="iso-8859-1" method="html" />
Un peu plus sur XPath XPath permet d’écrire des « chemins XML » mais également d’utiliser des fonctions et des opérateurs.
XPath : les « chemins » en quatre points Cours XSLT/XPath - Yves Laborde XPath : les « chemins » en quatre points XPath permet de pointer sur des éléments de l'arborescence du document. Une expression XPath est constituée (1) d'étapes (steps), séparées par des slashs, « / » Chaque étape contient (2) un nœud asserté (node test) qui sert à spécifier le nœud par : le nom d’un élément, d’un attribut, d’un espace de nom ou « * » (tous les types de nœuds : élts, attr, esp.noms). Optionnellement l’expression peut avoir (3) des prédicats (à droite de chaque node test) et (4) des axes (à gauche de chaque node test) L'expression retourne un sac de nœuds (node set) : les nœuds qui correspondent au dernier nœud asserté – si elle en trouve. Axe implicite .../.../.../Etapes/.../... [Prédicat]* "/CINEMA/SALLE[NO="1"]/SEANCES" Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde (1) les étapes Le slash « / » indique la relation parent / enfant Un double slash « // » indique la relation parent / descendants (i.e. en profondeur dans la hiérarchie). /CINEMA//SEANCES/SEANCE Note : temps de calcul accru Un slash en début fait partir l'expression de la racine du document : l'expression est donc indépendante du contexte. Un point « . » indique le nœud asserté en cours, on parle de contexte ou de nœud contexte Un double point « .. » indique le nœud parent du noeud contexte Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde Quelques cas... //SEANCE est-il identique à //SEANCES/SEANCE ? Note : "//..." part de la racine : //p : tous les p du document, à toute profondeur depuis la racine .//p : tous les p sous le nœud contexte Différences entre : //BBB/p Tous les p du document directement en dessous de tous les BBB //BBB//p Tous les p du document en dessous de tous les BBB Avec //BBB//p, chaque p est sélectionné une fois dans le sac de nœuds résultant, même si plusieurs BBB sont imbriqués et font différents chemins valides vers le même p : il n’y a jamais de doublon dans un sac de nœuds. Université Evry Val d'Essonne
(2) : les node tests (ou tests de nœuds) Cours XSLT/XPath - Yves Laborde (2) : les node tests (ou tests de nœuds) Chaque étape comprend un node test Le nœud cherché peut être une balise, un attribut (@nom) ou un nœud texte text()(qui renvoie le texte des nœuds sans celui de leurs fils) Existent également des valeurs génériques : *(tout type de nœud : élts, esp.noms), @*(tout attribut) , node()(tout nœud : texte, commentaires…) Le point "." indique le contexte actuel Le double point ".." permet de remonter d'un niveau dans l'arborescence. Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde Exemples //p/@id : retourne la valeur de l’attribut id, tandis que //p[@id]: retourne tous les nœuds p qui ont un attribut id Ne pas confondre un nœud texte et le texte contenu : /BOOK/text/front : retourne tous les nœuds front directement enfants de text ; avec value-of retourne la valeur (le texte) du premier nœud front, sans les balises imbriquées /BOOK/text/front/text() : retourne le texte de tous les nœuds front directement enfants du noeud text ; avec value-of retourne la valeur (le texte) du premier nœud front /BOOK/text/front/@id/text() Ne retourne rien ! Il n'y a pas de nœud texte descendant d'un attribut. (@id retourne la « valeur » de l’attribut) /SALLE/node() : retourne tous les types de nœuds fils de SALLE (éléments, commentaires...) Université Evry Val d'Essonne
(3) : les prédicats Chaque étape peut comprendre un ou plusieurs prédicat, qui est une expression XPath entre crochets placée après le node test. //chap[@title='1']sélectionne les chap dont l'attribut title vaut '1’ //p[@id][@name]retourne tous les nœuds p ayant les attributs id et name //*[@*='bbb'] retourne tous les nœuds ayant un attribut valant 'bbb' Le prédicat permet de filtrer les nœuds en ajoutant des conditions. L’expression dans le prédicat a deux valeurs : vraie ou fausse. L’expression est convertie si besoin en valeur booléenne : => est faux : un sac de nœud vide, le nombre zéro ou la chaîne vide, => est vrai : tout le reste. Dans le premier exemple, l’expression retourne déjà une valeur booléenne grâce à l’opérateur « = » //p[name] : sélectionne tous les p contenant un élément enfant name. p est le contexte de l’expression Xpath name. //*[@NO]: retourne tous les nœuds ayant un attribut NO //p[../liste] : retourne tous les p fils directs de liste
Fonctions XPath utiles Les conditions sur la position d’un nœud sont souvent utilisées dans les prédicats. Les fonctions last() et position() renvoie respectivement le numéro cardinal du dernier nœud d’un sac de nœuds et le numéro cardinal du nœud courant. Note : last() et position() s’écrivent toujours avec les parenthèses et sans argument. Plutôt que [position() = 1], pour demander les nœuds qui sont le premier enfant de leur père, on peut utiliser une notation courte : [1].
Exemples <xsl:for-each select="/hi[@rend = ‘italics’]"> <!-- tous les tags hi avec un attribut rend égal à ‘italics’ --> </xsl:for-each> <xsl:for-each select="/p[name/@id]"> <!-- tous les p ayant un enfant name qui a un attribut id --> <xsl:for-each select="/text/p [not(position()=last())]"> <!– tous les p qui ne sont pas les derniers parmi les p de parent text --> <xsl:for-each select="/text/p[position() != last())]"> <!– idem que précédemment <=> autre notation --> <xsl:for-each select="/text/p[position() >= 1]"> <!-- tous les p sauf le premier -->
Cours XSLT/XPath - Yves Laborde <xsl:value-of select="text/p[3]"/> <xsl:value-of select="text/p[name]"/> <xsl:value-of select="text/p/name"/> <xsl:value-of select="text[p/name]/p[3]"/> <xsl:value-of select="text/p[name/@n]"/> <xsl:value-of select="text/p[not(text())]"/> <xsl:value-of select="text/p[last()]"/> <xsl:value-of select="text/p[not(position() = last())]"/> Element text Element p Element p Element p Element p Text Text Text Element name id='p5' n='8' Text Université Evry Val d'Essonne
(4) : les axes Dans la forme abrégée de la syntaxe XPath utilisée jusqu'ici, les node test sont cherchés parmi les enfants avec /, ou parmi les descendants avec //. Il est donc impossible avec cette notation d'indiquer un chemin qui remonte vers les autres directions : ancêtres, parents, ou frères du nœud contexte. C’est ce que permettent les axes.
XML, une histoire de famille Cours XSLT/XPath - Yves Laborde XML, une histoire de famille Document / Ascendants Prologue <?xml version=“1.0”?> Element ROOT corpus Parent Element text Element p Frères précédents Element p Element p Element p Frères suivants Enfants Text Text Text Element name Text Text Descendants Université Evry Val d'Essonne
<?xml version=“1.0”?> XML, une histoire de famille Ascendants Document / Prologue <?xml version=“1.0”?> Element ROOT FitnessCenter Parent Element Member Frères précédents Frères suivants Element Phone Element Name Element Phone Element FavoriteColor Enfants Text Jeff Element Name Text 555-4321 Text lightgrey Descendants Text Jeff
Noter les axes On peut désigner à chaque étape d'autres directions que l’axe parent/enfant grâce à une « notation longue » : le note test est précédé du nom de l'axe suivi de "::" Exemple select="./ancestor::div" Select="./ancestor::SALLE/TITRE following-sibling::node() | preceding-sibling::node() Recherche tous les div parmi les ascendants Remonte aux SALLE ascendant, puis descend à son enfant direct TITRE Sélectionne tous les nœuds descendant du même père respectivement à droite et à gauche En anglais : « sibling » signifie « enfant de même parent »
<?xml version=“1.0”?> Document / PI <?xml version=“1.0”?> Element ROOT FitnessCenter Element Member ancêtre Element Name Element Phone Element Phone Element FavoriteColor Frêre précédent Frêres suivants Text Jeff Text 555-1234 Text 555-4321 Text lightgrey ancestor::* sélectionne tous les ancêtres, c-à-d : - Member - FitnessCenter preceding-sibling::* sélectionne tous les frères à gauche, c-à-d : - Name following-sibling::* sélectionne tous les frères à droite, c-à-d : - Phone - FavoriteColor
<?xml version=“1.0”?> Document / PI <?xml version=“1.0”?> Element ROOT FitnessCenter descendants Element Member Element Name Element Phone Element Phone Element FavoriteColor Text Jeff Text 555-1234 Text 555-4321 Text lightgrey À partir de FitnessCenter, descendant::* ou //* sélectionne tous les descendants, c-à-d : - Member - Name - Phone, etc.
Liste des axes ancestor: sélectionne tous les ancêtres ancestor-or-self: sélectionne le nœud courant et tous ses ancêtres attribute: sélectionne tous les attributs child: sélectionne tous les enfants (descendants directs) descendant: sélectionne tous les descendants descendant-or-self: sélectionne le nœud courant plus tous ses descendants following: sélectionne tout ce qui suit le nœud courant dans le document following-sibling: sélectionne tous les frères à droite namespace: sélectionne tous les namespaces ouverts parent: sélectionne le parent preceding: sélectionne tout ce qui précède le nœud courant dans le document preceding-sibling: sélectionne tous les frères à gauche self: sélectionne le nœud courant
Abréviations utiles L'axe « child:: » est l'axe par défaut « @ » abrège l'axe « attribute:: » « // » abrège l’axe « descendant-or-self:: » « . » abrège « self:: » « .. » abrège l'axe « parent:: » « / » abrège la racine
Principaux opérateurs Cours XSLT/XPath - Yves Laborde Principaux opérateurs Opérateurs arithmétiques +, -, *, div, mod Note : une balise XML peut contenir un tiret, il faut donc encadrer “-” d’espace. Operateurs booléens : not, and, or Operateurs relationnels : <, >, =, <=, >=, !=, | (ou), & (et) < et > doivent être notés < et > pour satisfaire aux contraintes XML Pour exprimer : Noter : < > = <= >= != < > = <= >= != Université Evry Val d'Essonne
Rappel XML : ordre des éléments et valeur des attributs Cours XSLT/XPath - Yves Laborde Rappel XML : ordre des éléments et valeur des attributs On ne peut pas accéder aux attributs par leur numéro d'ordre : ils sont accessibles seulement par leur nom, leur ordre n'est pas signifiant. impossibles : @titre[1] ou //*[@titre[1]] Ainsi, dans la conception d'un document XML, il ne faut pas confier d'information à l'ordre des attributs. Les éléments correspondent un peu aux structures de données informatiques dites "tableaux" et les attributs aux tableaux associatifs ou "hashes" Université Evry Val d'Essonne
Expression de conditions Opération sur les chaînes
xsl:if <xsl:if test="expression XPath"/> Permet de filtrer ou de choisir entre différentes possibilités. Si l’expression XPath de @test renvoie une valeur non nulle ou vraie, alors le contenu de xsl:if est exécuté. <xsl:if test="//SEANCE"> <p> Il existe au moins une séance de programmée ! </p> </xsl:if>
Exemples de xsl:if <xsl:for-each select="name"> <xsl:if test="@type='person'"> <xsl:value-of select='.'> </xsl:if> </xsl:for-each> Remarquez qu’en fait, c’est équivalent à : <xsl:for-each select="name[@type='person']"> <xsl:value-of select='.'> </xsl:for-each>
Dans le contexte de xsl:if, XPath retourne une valeur booléenne Cours XSLT/XPath - Yves Laborde Dans le contexte de xsl:if, XPath retourne une valeur booléenne Une expression XPath peut être utilisée avec xsl:if pour voir si elle retourne vrai ou faux : elle retourne vrai si elle retourne : - un sac de nœuds non vide - une valeur numérique différente de 0 - une valeur booléenne vraie - une chaîne de caractères non vide elle retourne faux dans les cas contraires Université Evry Val d'Essonne
xsl:choose Exprimer des alternatives avec xsl:choose. Le premier élément when dont le test est positif est exécuté sinon, si otherwise existe, ses éléments sont exécutés <xsl:choose> <xsl:when test='expression XPath'> [action] </xsl:when> <xsl:otherwise> </xsl:otherwise> </xsl:choose>
Extraire une sous-chaîne Dans un nœud texte, on peut extraire une sous chaîne. ex. Extraire l’année seule dans "février-2009" Utiliser la fonction XPath "substring-after()" qui prend deux arguments : La chaîne source La chaîne à partir de laquelle sélectionner le texte (pattern). substring-after(chaîne, pattern) <xsl:if test="docDate"> <xsl:text> (année: </xsl:text> <xsl:value-of select= "substring-after(docDate, '-')" /> <xsl:text>)</xsl:text> <xsl:if>
Extraire une sous-chaîne docDate substring-after(docDate, ‘-’) février-2010 2010 XPath dans ce cas retourne une chaîne, et non plus un « sac de nœuds ». En attendant XSLT 2.0 et les expressions régulières, les fonctions chaînes de XPath paraissent rudimentaires :
Fonctions sur des chaînes Cours XSLT/XPath - Yves Laborde Fonctions sur des chaînes Ces fonctions retournent une chaîne : substring-before(chaîne, pattern) substring-after(chaîne, pattern) substring(chaîne, index, len?) ex: substring(‘1234567890’, 2, 5) => ‘23456’ string-length(chaîne) ex: string-length(‘1234567890’) => 10 concat(chaîne cible, chaîne à ajouter) Deux fonctions retournent une valeur booléenne : starts-with() ex: <xsl:if test="starts-with(docDate, 'va')”> [action] </xsl:if> contains(chaîne à tester, chaîne test) ex: <xsl:for-each select="docDate[contains(.,'2010')] "> <!-- Sélectionne les nœuds contenant 2010 --> Université Evry Val d'Essonne
Tester la présence d’une sous-chaîne Par exemple, on veut récupérer les éléments en italique ayant la valeur IT dans l'attribut @rend. Mais @rend peut également contenir "IT BO" ou "BO IT" pour marquer italique + gras, etc. On ne les extraira pas avec : select="//*[@rend = 'IT']", qui recherchera les @rend avec comme valeur exacte IT. contains permet ici de récupérer tous les italiques : select="//*[contains(@rend, 'IT')]"
XSL et le traitement des chaînes Ces fonctions ne sont utiles que sur des contenus très normalisés. XSLT n’est pas adapté au traitement de chaînes de caractères. Il est impossible par exemple de s’en servir pour extraire les phrases d'un texte en se basant sur la ponctuation.
Quantifier
count(), la fonction magique Cours XSLT/XPath - Yves Laborde count(), la fonction magique Cette fonction XPath permet de retourner le nombre de nœuds trouvés dans l’expression XPath entre parenthèses Permet de dénombrer tout phénomène exprimé en XML <xsl:value-of select= "count(//p[@type = 'intro'])"/> "count(//*[@lang = 'en'])"/> "count(//div/p[1]/*[@ana= 'exemple'])"/> Université Evry Val d'Essonne
Utiliser des variables Jusqu’à présent on a systématiquement mis le résultat d’une expression XPath dans xsl:value-of, qui affiche directement le résultat. Mais si l’on veut stocker et manipuler la valeur, pour afficher par exemple un pourcentage plutôt que le chiffre brut ?
xsl:variable xsl:variable permet de stocker puis de réutiliser une chaîne ou un fragment d’arbre. On crée une variable avec xsl:variable : <xsl:variable name='hello' select="hello world"/> @name : pour lui donner un nom @select : calculer sa valeur (expression XPath ou texte littéral) On désigne la valeur de la variable avec le nom préfixé de « $ » dans une expression Xpath : <xsl:value-of select="$hello"/> Nom de la variable : hello hello world Valeur de la variable :
Stocker une valeur calculée Cours XSLT/XPath - Yves Laborde Stocker une valeur calculée Définition de 3 variables : <xsl:variable name="nbrChap" select="count(//chap)" /> <xsl:variable name="nbrChap1" select="count(//chap[@title='1'])" /> <xsl:variable name="nbrChap2" select="count(//chap[@title='2'])" /> Calcul du pourcentage de chapitres de niveau 1 : <xsl:value-of select="($nbrChap1 * 100) div $nbrChap" /> Calcul du pourcentage de chapitres de niveau 2 : select="($nbrChap2 * 100) div $nbrChap" /> Évite de recalculer plusieurs fois count(//chap) Code plus rapide et plus modulaire (raffinement) Université Evry Val d'Essonne
Portée des variables Une variable reste utilisable dans tout l’élément dans lequel elle a été déclarée dans la feuille de style et dans les sous-éléments de celui-ci. Une fois sortie de cet élément, elle est détruite Une variable déclarée directement comme enfant de xsl:stylesheet peut être utilisée dans toute la feuille de style. Une variable déclarée dans un élément (xsl:template, xsl:if, etc.) ne peut être utilisée que dans cet élément et ses sous-éléments.
Quelques fonctions arithmétiques sum(node set) calcule la somme de toutes les valeurs présentes dans le node set round(number) arrondit number à l’entier le plus proche Exemple round(2.3) retourne 2 etc.
Utiliser un template pour calculer les pourcentages Problème : on répète n fois la même opération pour calculer des pourcentages Solution : factoriser cette opération XSLT permet de créer une sous-routine (un template) qui retourne une valeur en fonction d'arguments
<xsl:template match="/"> <xsl:variable name="nbrChap" select="count(//chap)" /> <xsl:variable name="nbrChap1" select="count(//chap[@title= '1'])" /> <xsl:variable name="nbrChap2" select="count(//chap[@title= '2'])" /> Calcul du pourcentage de section de niveau 1 : <!– Les calculs de pourcentages sont réalisés en appelant le template (procédure), auquel on transmet les arguments --> <xsl:call-template name="calculPourcentage"> <xsl:with-param name="Nbr1" select="$nbrChap1"/> <xsl:with-param name="Nbr2" select="$nbrChap2"/> </xsl:call-template> Calcul du pourcentage de section de niveau 2 : <!– idem en fournissant les arguments $nbrChap1 et $nbrChap1 --> <!– TEMPLATE: procédure de calcul des pourcentages --> <xsl:template name="calculPourcentage"> <xsl:param name="Nbr1"/> <xsl:param name="Nbr2"/> <xsl:value-of select="($Nbr1 * 100) div $Nbr2"/> </xsl:template> Déf. des 3 variables comme précédemment Appel du template xsl:with-param permet de transmettre les arguments xsl:param permet de nommer les arguments reçus Définition du template
L'intérêt d'une approche "procédurale" Nous avons vu une façon d'utiliser XSLT où l'on sait où chercher l'information à extraire. Cette démarche est adaptée pour les cas où l'on fait une extraction de faible volume dans des endroits précis de la structure. Mais…
L'approche par templates
L'intérêt d'une approche par templates Si l'on veut – plutôt qu'extraire un élément – recopier la totalité du document sauf un élément ? Ou si l'on veut extraire un grand nombre d'éléments ? XML a une structure non limitée : il faudrait un nombre irréaliste de for-each et if Il est plus économique dans ce cas d'indiquer ce que l'on veut enlever ou modifier que ce que l'on veut extraire.
Plutôt que de décrire des opérations, on dessine un nouvel arbre en indiquant seulement les points à modifier de l'arbre existant.
Retour en arrière Toutes les feuilles de style commençaient par <xsl:template match="/"> Cet élément xsl:template sert à regrouper des actions à faire à un "moment" précis Ce moment est désigné dans l'attribut @match @match attend une expression XPath, ici "/" indique la racine du document. Un template avec match="/" est exécuté en premier, puisque la racine est la première chose que cherche le processeur.
Comment utiliser les templates ? Il suffit de prévoir pour l’élément que l’on veut traiter un élément template avec un @match qui lui correspond. @match peut correspondre à tout nœud : élément, attribut (avec @), texte (avec text()) ou commentaire (avec comment()). Exemple : un template qui s’appliquera à chaque élément <SALLE> dans le document : <xsl:template match= "SALLE"> ... <xsl:template>
Exemple : mettre un titre HTML à chaque texte <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match= "SALLE"> <h1>Autre séances : <xsl:value-of select=".//SEANCE" /> </h1> <xsl:apply-templates /> </xsl:template> </xsl:stylesheet> Cette nouvelle règle permet de relancer l’analyse et donc de la continuer comme le traitement du document...
xsl:apply-templates Dans l'exemple précédent, apply-templates sert à relancer l'analyse (la recherche d'un template avec un attribut match qui correspond) dans la sous-arborescence (les descendants) du nœud traité par le template Si on ne met pas apply-templates le processeur est « éteint », il abandonne tout ce qui est en deçà (i.e. la sous-arborescence) !
Cours XSLT/XPath - Yves Laborde Que fait le processeur ? Après avoir construit une représentation du document, le processeur rentre dans l'arborescence. Il cherche dans la feuille de style un template qui correspond à sa première position, qui est "/" S'il n'en trouve pas, il passe aux descendants et recommence. S’il trouve un nœud texte, il imprime son contenu. Université Evry Val d'Essonne
Cours XSLT/XPath - Yves Laborde Le processeur parcours les éléments dans un ordre prévisible et leurs attributs dans un ordre non prévisible. Document / PI <?xml version=“1.0”?> Element corpus Element text Element p Element p Element p Element p Text Text Text Element name Text Text Université Evry Val d'Essonne
Que fait le processeur ? (suite) Tant que parmi les descendants le processeur ne trouve pas de templates à appliquer, il continue à descendre dans l’ordre enfant / frère, en imprimant les nœuds texte. Si un template avec match="p" est défini, le processeur l’applique, sinon il descend au nœud texte, l’imprime, et remonte au p suivant Element p Element p Idem : s’il n’existe pas de template pour name, passe aux nœuds enfants Text Element name
Que fait le processeur ? (suite) Si un template correspond, le processeur l’exécute, et ne passe aux descendants que lorsqu’il est explicitement relancé avec l’instruction xsl:apply-templates <xsl:template match="p"> <p><xsl:apply-templates /></p> </xsl:template> Ce template est exécuté à chaque p rencontré. Une balise p est ouverte, l’analyse reprend dans la sous-arborescence (d’autres templates peuvent être exécutés), puis le p est fermé Element p Element p <xsl:template match="name"> M. *** </xsl:template> Text Element name Toutes les balises name et leurs contenus sont remplacés par « M. *** ».
L’enchâssement Dans un template, l’ instructions, xsl:apply-templates a un effet spécial : elle relance la recherche de templates parmi les enfants. Quand le processeur a fini de traiter les descendants, il reprend et termine l’exécution du template d'où il est parti du fait de l'instruction apply-templates Sinon, il ne rentre pas dans la sous-arborescence. Avec les xsl:apply-template les templates sont donc "enchâssés" autant de fois que nécessaire pendant l'exécution. xsl:template permet de traiter les éléments inclus, contrairement à value-of
L'enchâssement (2) 1. Ligne imprimée en tout premier 2. Passe à la descendance, alors que le template n'est pas fini. Imprime le texte contenu dans les éléments sauf p qui est traité explicitement <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html><body> <xsl:apply-templates /> </body> </html> </xsl:template> <xsl:template match="p"> <item><xsl:value-of select="." /> </item> </xsl:stylesheet> 3. Tous les p sont traités mais pas leurs descendants car le processeur n'a pas été relancé avec xsl:apply-templates ! 4. Quand la descendance est traitée, "remonte" de "templates appelant" en "templates appelant" et fini chacun. Cette ligne est donc imprimée en tout dernier
Utilisation de xsl:apply-templates On peut mettre plusieurs xsl:apply-templates dans le même template. C’est le cas lorsque l’on ne veut pas parcourir tout le document mais seulement certaines parties. C’est aussi le cas lorsque l’on veut procéder à l’analyse selon un ordre particulier ou que l’on veut traiter les attributs après les descendants. Etc. <xsl:template match="/"> <html><body> <h1>1. les salles</h1> <xsl:apply-templates select="//SALLE"> <h1>2. les numéros de salles</h1> <xsl:apply-templates select="//SALLE/@NO"> </body></html> </xsl:template>
apply-templates : utiliser @select Cours XSLT/XPath - Yves Laborde apply-templates : utiliser @select @select permet de préciser au processeur où reprendre la recherche de templates <xsl:template match="/"> <liste_seances> <xsl:text> Cinéma: <xsl:value-of select="//NOM" /> </xsl:text> <xsl:apply-templates select="//SALLE"/> </liste_seances> </xsl:template> <xsl:template match="SALLE"> <item>Salle <xsl:value-of select="./@NO" /> : <xsl:for-each select=".//SEANCE" /> <horaire><xsl:value-of select=".//SEANCE" /> </horaire> </xsl:for-each/> </item> Ici on passe directement aux <SALLE> Ici on devrait également utiliser xsl:apply-templates plutôt que for-each (qui reste une approche procédurale) !!! Université Evry Val d'Essonne
apply-templates : utiliser @select Cours XSLT/XPath - Yves Laborde apply-templates : utiliser @select Document transformé : <liste_seances> Cinéma: Epée de bois <item>Salle 1 : <horaire>15:00</horaire> <horaire>18:00</horaire> <horaire>21:00</horaire> </item> <item>Salle 2 <horaire>22:00</horaire> </liste_seances> Université Evry Val d'Essonne
apply-templates : utiliser @select @select permet ici de descendre directement plus bas dans la sous-arborescence en "sautant" toute une partie. On peut aussi désigner un endroit qui n'est pas dans la sous arborescence (en évitant de produire une boucle infinie !). Note : par défaut, un xsl:apply-templates contient un @select="node()" qui lui fait sélectionner ses enfants
Supprimer les balises Une feuille de style contenant ce seul template recopie le document source en enlevant toutes les balises : <xsl:template match="/"> <xsl:apply-templates /> </xsl:template> EN effet, par défaut, dans tous les nœuds où il ne trouve pas de xsl:template qui s’applique, le processeur imprime le contenu pour les nœuds de type texte et passe aux enfants pour les autres types de nœuds.
Supprimer du texte Plutôt que d'indiquer au processeur des chemins à parcourir qui excluent certaines parties de texte, on peut modifier son action par défaut (recopier le texte) sur les nœuds à exclure : <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match=”NOM | ADRESSE | METRO | …"> <!– le template ne contient rien : ni action, ni relance du processeur avec apply-templates. Le contenu est donc abandonné --> </xsl:template> </xsl:stylesheet>
La clef : les templates par défaut Cours XSLT/XPath - Yves Laborde La clef : les templates par défaut Pourquoi, par défaut, le processeurs descend dans l'arborescence et imprime les nœuds textes ? Une feuille de style a deux templates par défaut ; Ces templates sont appliqués quand le processeur ne trouve pas dans la feuille de style un template correspondant au nœud traité Correspond à la racine (/) ou (|) à tout élément (*). Action = avancer le processeur aux enfants (incluant élément, attribut et nœud texte car apply-template a par défaut @select=“node()”), et leur appliquer les templates. <xsl:template match="/ | *”> <xsl:apply-templates/> </xsl:template> <xsl:template match="text()”> <xsl:value-of select="."/> </xsl:template> Correspond à tout nœud texte. Action = imprimer son contenu Université Evry Val d'Essonne
Quand plusieurs templates peuvent s’appliquer… pourquoi le processeur applique : <xsl:template match= "SALLE"> et non le template par défaut : <xsl:template match="/ | *">, alors que les deux sont en concurrence ? => Le processeur applique le template le plus spécifique. On peut utiliser cette propriété pour prévoir un cas général et des cas particuliers : @match="p" : s’applique à tous les p @match="p[1]" : s’applique à tous les aînés des fratries.
Redéfinir les templates par défaut On peut redéfinir les templates par défaut pour modifier le comportement du processeur. Si on ajoute <xsl:template match="text()"> </xsl:template> le processeur parcours toujours l'arborescence mais n'imprime plus les nœuds textes.
Exemple de modification des templates par défaut On veut extraire du document seulement le contenu des nœuds REMARQUE. Dans ce cas de figure la majorité du document est à exclure, seul un tag est à conserver. On peut utiliser deux possibilités : Indiquer le chemin qui mène aux nœuds voulus Laisser le cheminement par défaut dans l'arborescence, mais modifier le comportement par défaut pour ne pas recopier les nœuds textes
Méthode 1 Laisser le comportement par défaut, mais utiliser @select pour mener directement sur les REMARQUE <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <xsl:apply-templates select="//REMARQUE"> </xsl:template> </xsl:stylesheet>
Méthode 2 On modifie le comportement par défaut : on laisse le cheminement dans l'arborescence, mais les nœuds textes ne sont plus recopiés, sauf pour le nœud voulu. <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="text()"> </xsl:template> <xsl:template match="REMARQUE"> <REMARQUE><xsl:value-of select='.'/></REMARQUE> </xsl:stylesheet>
Pour résumer (1) Le processeur parcours l’arborescence, piloté par des templates, qui peuvent l'arrêter à des endroits précis, exécuter des instruction XSLT, et le relancer Quand il ne trouve pas de template à appliquer, le processeur parcours l'arborescence, relancé par un template par défaut, dans un ordre enfants vers frères, et imprime le texte. A moins qu’un template capte le processeur dans l’arborescence et ne le relance pas, l’arbre est parcouru entièrement, et tous les nœuds textes sont répliqués.
Cours XSLT/XPath - Yves Laborde Pour résumer (2) Avec des templates on pilote le processeur : En insérant des templates à des points avec match En relançant ou non avec apply-templates En sélectionnant des sous arbres avec @select En utilisant ou modifiant les templates par défaut. L’ensemble de ces moyens d’action permet d'utiliser cette approche déclarative (par template) comme la plus économique pour décrire une transformation de l’arborescence source en une arborescence cible. Université Evry Val d'Essonne
Grouper
Extraire les valeurs différentes Comment produire une liste sans doublon des valeurs de @lang ? Avec <xsl:for-each select="//@lang"> la liste produite peut contenir plusieurs fois la même valeur. Comment regrouper les nœuds sur une valeur commune ? Par exemple à partir de plusieurs tag correction (<corr resp="DC" date="12-06-2002">), les classer par correcteur sans les connaître à l'avance.
Cours XSLT/XPath - Yves Laborde Solution : xsl:key xsl:key déclare une variable dans laquelle des nœuds sont regroupés par "clefs". xsl:key a trois attributs obligatoires : @name : donne un nom à la variable @match : une expression XPath indiquant les nœuds à collecter @use : une expression XPath indiquant quelle valeur utiliser pour grouper ces nœuds. Université Evry Val d'Essonne
On recherche les tags corr <xsl:key name="grouperParResp" match="//corr" use="@resp" /> On les groupes selon la valeur de leur attribut @resp (le contexte de cette expression XPath est le nœud corr) en se <corr sic='désaisissant' resp='DB'>dessaisissant</corr> ... <corr sic='desine' resp='DB'>dessine</corr> déjà les traits ... <corr sic='l'originial' resp='CF'>l'original</corr> ... <corr sic='uotre' resp='CF'>notre</corr> DB CF <corr sic='désaisissant' resp='DB'>dessaisissant</corr> <corr sic='desine' resp='DB'>dessine</corr> <corr sic='l'originial' resp='CF'>l'original</corr> <corr sic='uotre' resp='CF'>notre</corr> Clefs Nœuds collectés
L’élément key définit un groupe de nœud, lui attribue un nom et définit l’expression (la clef) qui permet de différencier les nœuds au sein de ce groupe.
Utilisation Une fois créée une variable xsl:key peut être utilisée pour obtenir les nœuds associés à une clef. la fonction XPath key(nom_table, clef) retourne tous les nœuds associés à l'entrée clef dans la table nom_table <xsl:for-each select="key(grouperParResp, 'DB')"> Texte d'origine : <xsl:value-of select="@sic"/> Texte corrigé : <xsl:value-of select="."/> </xsl:for-each> Texte d'origine : désaisissant Texte corrigé : dessaisissant Texte d'origine : desine Texte corrigé : dessine Appliqué à l'exemple précédent :
Trouver les valeurs uniques Avec la fonction key() on ne peut que retrouver les nœuds associés à une clef, on ne peut pas lister directement les clefs d'une variable xsl:key. Pour une liste de valeurs différentes, par exemple la liste des valeurs utilisées dans @lang, il faut utiliser une méthode détournée : utiliser une expression qui extrait un élément de chaque groupe correspondant à une clef. Par exemple ne prendre que les éléments dont l'index dans le groupe dont il fait parti est 1 Pour savoir si un nœud est le même que le premier retourné par un groupe , on peut comparer la valeur que retourne generate-id() qui retourne un identifiant unique constant pour chaque nœud.
Exemple <xsl:key name="langues" match="//@lang" use="."/> <xsl:for-each select="//@lang[generate-id(.)= generate-id(key(Langues', .)[1])]"> ... key(Langues', .) retourne le groupe des nœuds doublons du nœud traité. key(Langues', .)[1] retourne le premier élément du groupe generate-id retourne un identifiant unique pour un nœud. L'id du nœud contexte doit être le même que l'id du premier nœud du groupe des nœuds doublons. On sélectionne uniquement le premier nœud de chaque groupe, donc un nœud par groupe.
Cette méthode peut être utilisée avec un nœud différent entre match et use : <xsl:key name="Langue" match="*[@lang]" use="@lang"/> <table> <tr> <td>Langues</td> <td>Nombre d'éléments dans cette langue</td> </tr> <xsl:for-each select="//*[@lang and generate-id(.)= generate-id(key('Langue', @lang)[1])]"> <td><xsl:value-of select="@lang" /></td> <td><xsl:value-of select="count(key('Langue', @lang))"/> </td> </xsl:for-each> </table>
@use peut être n'importe quelle expression calculée @use peut être n'importe quelle expression calculée. Par exemple on peut grouper les p en fonction du nombre de notes qu’ils contiennent xsl:key name="pParNote" match="//p" use="count(note)« On peut imaginer maintenant de regarder pour chaque groupe la position moyenne en début ou fin de texte, etc.
Ajout d’information, Editer le corpus source
Jusqu’ici XSLT était utilisé pour extraire des données, pas pour éditer le corpus source. XSLT impose de nombreuses limites à une utilisation pour ajouter de l’informations : il est difficile de « recopier » à l’identique. L’édition d’un corpus avec XSLT ne peut donc se faire que sur des corpus très normalisés.
Recopier à l’identique : copy-of A La différence de value-of, copy-of retourne la représentation textuelle de l’arborescence. xsl:copy-of ne permet pas d’ajouter de l’information, mais illustre les limites de la duplication à identique, par exemple la perte du prolog (<!DOCTYPE...) que XSLT ne prend pas en charge <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";> <xsl:template match="/"> <xsl:copy-of select="." /> </xsl:template> </xsl:stylesheet>
xsl:copy En utilisant récursivement la fonction copy dans un template, on peut obtenir cette duplication et définir des templates pour ajouter des modifications <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> </xsl:copy> </xsl:template> <!-- Les templates de modification : --> <xsl:template match="xptr[not(@id)]"> <!-- on supprime les xptr sans id. -->
xsl:element et xsl:attribut Pour générer des balises et des attributs on peut utiliser les éléments xsl:element et xsl:attribut qui permettent de les construire pas à pas. Les deux fonctions prennent un attribut name, qui sera le nom de la balise ou de l’attribut, et le texte contenu dans xsl:element et xsl:attribut deviendra le texte de l’élément ou la valeur créé.
Exemple 1 : déplacer un élément Dans un corpus les notes sont regroupées à la fin du document. Des éléments ptr ont permis d’enregistrer l’endroit des appels de note ; leur attribut @target permet de les associer à la note dont l’attribut @id correspond Le but est de remonter les notes, conformément aux prescription TEI, directement à leur point d’insertion dans le texte et supprimer les pointeurs ptr.
<xsl:template match="node() | @ <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="ptr"> <xsl:variable name="id" select="@target" /> <xsl:element name="note"> <xsl:for-each select="./ancestor::text/back/note[@id=$id]/@*"> <xsl:attribute name="{name(.)}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:for-each> <xsl:value-of select=".//ancestor::text/back/note[@id=$id]"/> </xsl:element> <xsl:template match="note"> Cf. ci-joint "ajout.xsl"
Conclusion
Limites d'XSLT Délicat pour l'ajout d'annotation au corpus Délicat de contrôler complètement la réécriture Lourd et insuffisant pour la manipulation des chaînes de caractère (les nœuds texte) Prévu pour la manipulation de la structure, de l'encodage plus que du contenu des nœuds textes Inutilisable avec de très gros documents Prévoir dix fois la taille du fichier en mémoire vive. Ces limites sont dues à l'approche "arborescente" : XSLT permet de manipuler une arborescence en mémoire. Une autre représentation du contenu, dite "séquentielle" permet plus de précision et n’est pas limité par la taille du document, mais demande l’utilisation d’un langage de programmation.
Efficacité comme langage de requête Deux stratégies à cumuler : à dominante procédurale ou déclarative. Economie et plasticité grâce à l’utilisation de templates et templates par défaut. Adapté à l’extraction d’information, la projection de sous-corpus ou la conversion vers d’autres formats. La version 2 de XSLT apportera des améliorations (expressions régulières, typage, regroupement), sans changer cette dominante « extraction », plus que « édition », dans la « transformation »