Introduction à XSLT - cours 4 Éric Laporte Institut Gaspard-Monge Université Paris-Est Marne-la-Vallée
Sommaire Regrouper des entrées 4 Introduire des références 12 Produire un index 22 Extraire des informations d'un document mal structuré 37 Rendre explicite une structure implicite 44 Produire plusieurs documents en même temps 52 Analyser du texte 57
30. Expressions relatives 32. Axes Xpath (1/6) 33. Axes (2/6) 34. Axes (3/6) 35. Axes (4/6) 36. Axes (5/6) 37. Axes (6/6) 38. Extraction à partir d'un document mal structuré (1/7) 39. Extraction à partir d'un document mal structuré (2/7) 40. Extraction à partir d'un document mal structuré (3/7) 41. Extraction à partir d'un document mal structuré (4/7) 42. Extraction à partir d'un document mal structuré (5/7) 43. Extraction à partir d'un document mal structuré (6/7) 44. Extraction à partir d'un document mal structuré (7/7) 45. Donner une structure à un document "aplati" (1/7) 46. Donner une structure à un document "aplati" (2/7) 47. Donner une structure à un document "aplati" (3/7) 48. Donner une structure à un document "aplati" (4/7) 49. Donner une structure à un document "aplati" (5/7) 50. Donner une structure à un document "aplati" (6/7) 51. Donner une structure à un document "aplati" (7/7) 52. Résultat 53. Produire plusieurs documents (1/3) 54. Produire plusieurs documents (2/3) 55. Produire plusieurs documents (3/3) 56. Résultat : l'index 57. Résultat : le catalogue 58. Analyser du texte (1/2) 59. Analyser du texte (2/2) 4. Objectifs 5. Grouper par albums (1/4) 6. Résultat 7. Grouper par albums (2/4) 8. Grouper par albums (3/4) 9. Grouper par albums (4/4) 10. Résultat 11. Paramètres du script XSLT (1/2) 12. Paramètres du script XSLT (2/2) 13. Introduire des références à d'autres entrées (1/5) 14. Résultat 15. Introduire des références à d'autres entrées (2/5) 16. Introduire des références à d'autres entrées (3/5) 17. Introduire des références à d'autres entrées (4/5) 18. Introduire des références à d'autres entrées (5/5) 19. Variante avec identifiants (1/3) 20. Variante avec identifiants (2/3) 21. Résultat 22. Variante avec identifiants (3/3) 23. Index des horaires de métro (1/7) 24. Index des horaires de métro (2/7) 25. Index des horaires de métro (3/7) 26. Index des horaires de métro (4/7) 27. Index des horaires de métro (5/7) 28. Index des horaires de métro (6/7) 29. Index des horaires de métro (7/7)
Objectifs Réorganiser la structure d'un document XML Certains documents sont mal structurés (récupérés à partir de documents plats) Certains documents sont conçus pour un usage puis utilisés pour autre chose Ajouter des informations redondantes (exemple : un index alphabétique)
Grouper par albums (1/4) Regrouper les pistes qui appartiennent à un même album <xsl:template match="Tracks"> <xsl:for-each-group select="Track" group-by="Album"> <Album title="{current-grouping-key()}"> <xsl:apply-templates select="current-group()"/> </Album> </xsl:for-each-group> </xsl:template> <xsl:template match="Track"> <xsl:copy> <xsl:apply-templates select="*[name()!='Album']"/> </xsl:copy>
Résultat <?xml version="1.0" encoding="ISO-8859-1"?> <iTunes> <Major_Version>1</Major_Version> <Minor_Version>1</Minor_Version> <Application_Version>4.6</Application_Version> <Music_Folder>file://localhost/C:/My%20Music/</Music_Folder> <Library_Persistent_ID>B2BF2C09D305D49C</Library_Persistent_ID> <Album title="american beauty soundtrack"> <Track> <Track_ID>37</Track_ID> <Name>American Beauty - Theme</Name> <Artist>Air</Artist> <Kind>MPEG audio file</Kind> <Size>3948579</Size> <Total_Time>197407</Total_Time>
Grouper par albums (2/4) select spécifie les noeuds à grouper group-by spécifie la clé de groupement : expression évaluée à partir de chacun des noeuds à grouper, puis convertie en valeur textuelle Si un noeud à grouper a plusieurs clés, il figurera dans plusieurs groupes S'il n'a pas de clé, il ne figurera dans aucun groupe <xsl:for-each-group select="Track" group-by="Album"> <Album title="{current-grouping-key()}"> <xsl:apply-templates select="current-group()"/> </Album> </xsl:for-each-group>
Grouper par albums (3/4) Le contenu de <xsl:for-each-group> est exécuté une fois par groupe current-grouping-key() contient la clé courante current-group() contient les noeuds du groupe courant Le noeud courant est le premier noeud du groupe courant La liste de noeuds courante contient le premier noeud de chaque groupe <xsl:for-each-group select="Track" group-by="Album"> <Album title="{current-grouping-key()}"> <xsl:apply-templates select="current-group()"/> </Album> </xsl:for-each-group>
Grouper par albums (4/4) Si <xsl:for-each-group> contient <xsl:sort>, cela classe les groupes les uns par rapport aux autres <xsl:sort> est exécuté une fois pour tous les groupes Les instructions qui le suivent au même niveau sont exécutées une fois par groupe Le noeud contexte dans le <xsl:sort> est le premier noeud de chaque groupe <xsl:for-each-group select="Track" group-by="Album"> <xsl:sort select="current-grouping-key()" lang='fr'/> <Album title="{current-grouping-key()}"> <xsl:apply-templates select="current-group()"/> </Album> </xsl:for-each-group>
Résultat <?xml version="1.0" encoding="ISO-8859-1"?> <iTunes> <Major_Version>1</Major_Version> <Minor_Version>1</Minor_Version> <Application_Version>4.6</Application_Version> <Music_Folder>file://localhost/C:/My%20Music/</Music_Folder> <Library_Persistent_ID>B2BF2C09D305D49C</Library_Persistent_ID> <Album title="Absolute Reggae 2"> <Track> <Track_ID>61</Track_ID> <Name>Rendez-Vouz</Name> <Artist>Alpha Blondy</Artist> <Genre>Pop</Genre> <Kind>MPEG audio file</Kind> <Size>3380129</Size> <Total_Time>211200</Total_Time>
Paramètres du script XSLT (1/2) Paramétrer l'ordre alphabétique en fonction de la langue <xsl:strip-space elements="*"/> <xsl:param name="lang" select="'fr'"/> (...) <xsl:template match="Tracks"> <xsl:for-each-group select="Track" group-by="Album"> <xsl:sort select="current-grouping-key()" lang='$lang'/> <Album title="{current-grouping-key()}"> <xsl:apply-templates select="current-group()"/> </Album> </xsl:for-each-group> </xsl:template>
Paramètres du script XSLT (2/2) Déclaration en-dehors des règles L'attribut select (facultatif) donne la valeur par défaut Ligne de commande avec Saxon sous Windows > java -jar saxon8.jar -o par-album-param.xml iTunes.xml par-album-param.xsl lang=fr <xsl:strip-space elements="*"/> <xsl:param name="lang" select="'fr'"/> <xsl:template match="Tracks"> <xsl:for-each-group select="Track" group-by="Album"> <xsl:sort select="current-grouping-key()" lang='$lang'/>
Introduire des références à d'autres entrées (1/5) À la fin d'une entrée, ajouter des références aux autres plantes qui ont le même nom scientifique <xsl:template match="jr:PLANT"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> <xsl:for-each select="//jr:PLANT [jr:BOTANICAL=current()/jr:BOTANICAL] [not(. is current())]"> <seeAlso> <xsl:value-of select="jr:COMMON"/> </seeAlso> </xsl:for-each> </xsl:copy> </xsl:template>
Résultat <PLANT id="3"> <COMMON>Marsh Marigold</COMMON> <BOTANICAL> <GENUS>Caltha</GENUS> <SPECIES>palustris</SPECIES> </BOTANICAL> <ZONE>4</ZONE> <LIGHT>Mostly Sunny</LIGHT> <PRICE unit="euro">6.81</PRICE> <AVAILABILITY>051799</AVAILABILITY> <seeAlso xmlns:jr="http://igm.univ-mlv.fr/~laporte/jardinerie">Cowslip</seeAlso> </PLANT> <PLANT id="4"> <COMMON>Cowslip</COMMON>
Introduire des références à d'autres entrées (2/5) À chaque entrée, on parcourt toutes les autres... 2e solution : dans le document source, on indexe les entrées par les noms scientifiques <xsl:strip-space elements="*"/> <xsl:key name="botanical-to-plant" match="jr:PLANT" use="jr:BOTANICAL"/> (...) <xsl:variable name="meme-nom" select="key('botanical-to-plant', jr:BOTANICAL)"/> <xsl:for-each select="$meme-nom[not(. is current())]"> <seeAlso> <xsl:value-of select="jr:COMMON"/> </seeAlso> </xsl:for-each>
Introduire des références à d'autres entrées (3/5) CATALOG ... noeud à indexer PLANT PLANT ... COMMON BOTANICAL ZONE LIGHT clé d'indexation Bloodroot 4 Sanguinaria Canadensis Mostly Shady <xsl:strip-space elements="*"/> <xsl:key name="botanical-to-plant" match="jr:PLANT" use="jr:BOTANICAL"/>
Introduire des références à d'autres entrées (4/5) CATALOG ... noeud indexé PLANT PLANT ... COMMON BOTANICAL ZONE LIGHT clé d'indexation Bloodroot 4 Sanguinaria Canadensis Mostly Shady <xsl:variable name="meme-nom" select="key('botanical-to-plant', jr:BOTANICAL)"/>
Introduire des références à d'autres entrées (5/5) <xsl:key name="botanical-to-plant" match="jr:PLANT" use="jr:BOTANICAL"/> Spécification des noeuds à indexer (match) Fonctionne comme dans <xsl:template match="..."> Spécification des clés d'indexation (use) Expression Xpath évaluée à partir du noeud à indexer Convertie en liste de chaîne de caractères <xsl:variable name="meme-nom" select="key('botanical-to-plant', jr:BOTANICAL)"/> Renvoie la liste des noeuds indexés par la clé Une clé peut indexer plusieurs noeuds
Variante avec identifiants (1/3) Utiliser les identifiants d'entrées pour les références <?xml version="1.0" encoding="ISO-8859-1"?> <!-- plant_catalog_jr.xml --> <CATALOG xmlns="http://igm.univ-mlv.fr/~laporte/jardinerie"> <PLANT id="1"> <COMMON>Bloodroot</COMMON> <BOTANICAL> <GENUS>Sanguinaria</GENUS> <SPECIES>canadensis</SPECIES> </BOTANICAL> <ZONE>4</ZONE> <LIGHT>Mostly Shady</LIGHT> <PRICE unit="euro">2.44</PRICE> <AVAILABILITY>031599</AVAILABILITY> </PLANT> <PLANT id="2">
Variante avec identifiants (2/3) <xsl:strip-space elements="*"/> <xsl:key name="botanical-to-plant" match="jr:PLANT" use="jr:BOTANICAL"/> (...) <xsl:template match="jr:BOTANICAL"> <xsl:copy> <xsl:variable name="meme-nom" select="key('botanical-to-plant', .) [not(jr:BOTANICAL is current())]"/> <xsl:if test="$meme-nom"> <xsl:attribute name="same-name" select="$meme-nom/@id"/> </xsl:if> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template>
Résultat <PLANT id="16"> <COMMON>Violet, Dog-Tooth</COMMON> <BOTANICAL same-name="17 18"> <GENUS>Erythronium</GENUS> <SPECIES>americanum</SPECIES> </BOTANICAL> <ZONE>4</ZONE> <LIGHT>Shade</LIGHT> <PRICE unit="euro">9.04</PRICE> <AVAILABILITY>020199</AVAILABILITY> </PLANT> <PLANT id="17"> <COMMON>Trout Lily</COMMON> <BOTANICAL same-name="16 18">
Variante avec identifiants (3/3) Un nom d'attribut sans préfixe n'appartient à aucun espace de noms, même s'il y a un espace de noms par défaut Pour reconnaître l'attribut, ne pas utiliser le préfixe d'espace de noms <CATALOG xmlns="http://igm.univ-mlv.fr/~laporte/jardinerie"> <PLANT id="1"> <COMMON>Bloodroot</COMMON> <xsl:variable name="meme-nom" select="key('botanical-to-plant', .) [not(jr:BOTANICAL is current())]"/> <xsl:if test="$meme-nom"> <xsl:attribute name="same-name" select="$meme-nom/@id"/> </xsl:if>
Index des horaires de métro (1/7) ligne7.xml donne les horaires des premiers et derniers métros dans chaque station Faire un index des horaires 0:25 : La Courneuve - 8 Mai 1945 ; 0:27 : Fort d'Aubervilliers ; La Courneuve - 8 Mai 1945 ; 0:29 : Aubervilliers - Pantin - Quatre Chemins ; Fort d'Aubervilliers ; 0:31 : Aubervilliers - Pantin - Quatre Chemins ; Porte de La Villette ; 0:32 : Corentin Cariou ;
Index des horaires de métro (2/7) Indexer les <td headers="station"> par les horaires <tbody> (...) <tr> <td class="h"> <span/> </td> <td class="carte"> <a href="http://www.ratp.info/Proxi/proxi.php" onclick="proxi('604933;2435111'); return false;"> <img src="..." alt="Plan de quartier"/> </a> <td id="fort_d_aubervilliers" headers="station" class="gauche">Fort d'Aubervilliers</td> <td headers="pre_dep_sem fort_d_aubervilliers" class="espace"/> <td headers="pre_dep_sem fort_d_aubervilliers">5:30</td> <td headers="pre_dep_sem fort_d_aubervilliers">5:34</td>
Index des horaires de métro (3/7) tbody ... tr tr ... noeud à indexer td td td td td a Fort d'Aubervilliers 5:30 5:34 clés d'indexation
Index des horaires de métro (4/7) Indexer les <td headers="station"> par les horaires <xsl:strip-space elements="*"/> <xsl:key name="heure-station" match="xh:tbody/xh:tr/xh:td[@headers='station']" use="../xh:td[matches(.,'^[0-7]:[0-5][0-9]')]"/> <tbody> (...) <tr> <td id="fort_d_aubervilliers" headers="station" class="gauche">Fort d'Aubervilliers</td> <td headers="pre_dep_sem fort_d_aubervilliers" class="espace"/> <td headers="pre_dep_sem fort_d_aubervilliers">5:30</td> <td headers="pre_dep_sem fort_d_aubervilliers">5:34</td>
Index des horaires de métro (5/7) Parcourir l'ensemble des heures <xsl:template match="xh:table"> <xsl:for-each-group select="xh:tbody/xh:tr/xh:td[matches(.,'^[0-7]:[0-5][0-9]')]" group-by="."> <xsl:sort select="current-grouping-key()"/> <xsl:call-template name="horaire"> <xsl:with-param name="heure" select="current-grouping-key()"/> </xsl:call-template> </xsl:for-each-group> </xsl:template>
Index des horaires de métro (6/7) Pour une clé, parcourir les noeuds indexés par cette clé <xsl:template name="horaire"> <xsl:param name="heure" select="'not found'"/> <xsl:value-of select="$heure"/> <xsl:text> : </xsl:text> <xsl:for-each select="key('heure-station',$heure)"> <xsl:sort select="." lang="fr"/> <xsl:value-of select="."/> ; </xsl:for-each> <xsl:text> </xsl:text> </xsl:template>
Index des horaires de métro (7/7) <xsl:key name="heure-station" match="xh:tbody/xh:tr/xh:td[@headers='station']" use="../xh:td[matches(.,'^[0-7]:[0-5][0-9]')]"/> tr ... noeud à indexer td td td td td a Fort d'Aubervilliers 5:30 5:34 clés d'indexation
../../* .. . ../* @* @ * */*
ancestor::* preceding::* following::* parent::* self::* attribute::* preceding-sibling::* following-sibling::* self::* attribute::* @ child::* descendant::*
Axes Xpath (1/6) ... noeud à indexer a Fort d'Aubervilliers 5:30 5:34 <xsl:key name="heure-station" match="xh:tbody/xh:tr/xh:td[@headers='station']" use="following-sibling::xh:td[matches(.,'^[0-7]:[0-5][0-9]')]"/> tr ... noeud à indexer td td td td td a Fort d'Aubervilliers 5:30 5:34 clés d'indexation
Axes (2/6) *[.=':'] abréviation pour child::*[.=':'] ..[.=':'] parent::node()[.=':'] .[.=':'] self::node()[.=':'] @*[.=':'] attribute::*[.=':'] node()[.=':'] child::node()[.=':'] */*[.=':'] child::*/child::*[.=':'] ../*[.=':'] parent::node()/child::*[.=':'] ../xh:td[.=':'] parent::node()/child::xh:td[.=':'] ../../*[.=':'] parent::node()/parent::node()/child::*[.=':']
Axes (3/6) Certaines expressions n'ont aucune abréviation possible parent::xh:tr[.=':'] ../xh:tr[.=':'] parent::node()/child::xh:tr[.=':'] parent::*[.=':'] following-sibling::*[.=':'] Chaque étape peut avoir un ou plusieurs prédicats *[.=':']/* child::*[.=':']/child::* *[.=':'][position()=1]/* child::*[.=':'][position()=1]/child::* L'expression * ne sélectionne que des éléments, sauf dans @* et attribute::*
Axes (4/6) Parenthésage interdit chapitre/section|chapitre/figure OK chapitre/(section|/figure) interdit tr[@class='blue']|td[@class='blue'] OK (tr|td)[@class='blue'] interdit descendant::*|self::* OK (descendant|self)::* interdit descendant-or-self::* OK ancestor-or-self::* OK
Axes (5/6) //*[.=':'] /descendant-or-self::node()/child::*[.=':'] //xh:td[.=':'] /descendant-or-self::node()/child::xh:td[.=':'] .//.[.=':'] self::node()/descendant-or-self::node()/self::node()[.=':']
Axes (6/6) Ordre d'une liste de noeuds Sert à évaluer position() Pour la plupart des axes Ordre du document [position()=1] sélectionne le premier noeud Pour les axes qui "remontent" dans le document (ancestor - preceding-sibling - preceding - ancestor-or-self) De droite à gauche [position()=1] sélectionne le noeud le plus à droite ou le plus bas dans l'arbre
Extraction à partir d'un document mal structuré (1/7) ligne7.xml est structuré pour la visualisation uniquement Extraire les missions des premiers et derniers trains (liste des stations avec les heures de passage)
Extraction à partir d'un document mal structuré (2/7) ligne7.xml est structuré pour la visualisation On va indexer les horaires par les noms des stations <tr class="impair"> <td class="g"> <span/> </td> <td class="carte"> <a href="http://www.ratp.info/Proxi/proxi.php" onclick="proxi('601400;2425884'); return false;"> <img src="horaires_metro7.php_fichiers/picto_carte.gif" alt="Plan de quartier"/> </a> <td id="place_d_italie" headers="station" class="gauche"> <strong>Place d'Italie</strong> <td headers="pre_dep_sem place_d_italie" class="espace">6:00</td> <td headers="pre_dep_sem place_d_italie">6:06</td> <td headers="pre_dep_sem place_d_italie">6:10</td> <td headers="der_dep_sem place_d_italie" class="espace_2">1:03</td> <td headers="der_dep_sem place_d_italie">1:05</td>
Extraction à partir d'un document mal structuré (3/7) Indexer les horaires par les noms des stations tr ... noeud à indexer td td td td td a Fort d'Aubervilliers 5:30 5:34 clé d'indexation
Extraction à partir d'un document mal structuré (4/7) Indexer les horaires par les noms des stations <xsl:strip-space elements="*"/> <xsl:key name="mission-1" match="xh:tbody/xh:tr/xh:td[position()=4]" use="preceding-sibling::xh:td[@headers='station']"/> <xsl:key name="mission-2" match="xh:tbody/xh:tr/xh:td[position()=5]"
Extraction à partir d'un document mal structuré (5/7) <xsl:template match="xh:table"> <missions> <mission> <!-- parcourir les noms des stations --> <xsl:apply-templates select="xh:tbody/xh:tr/xh:td[@headers='station']"> <xsl:with-param name="index-station-heure" select="'mission-1'"/> </xsl:apply-templates> </mission> (...) <xsl:template match="xh:td"> <xsl:param name="index-station-heure" select="'not found'"/> <xsl:variable name="heure" select="key($index-station-heure,.)"/> <xsl:if test="$heure/text()"> <!-- récupérer l'heure de l'arrêt --> <arret heure="{$heure}"> <xsl:value-of select="."/> </arret> </xsl:if> </xsl:template>
Extraction à partir d'un document mal structuré (6/7) Résultat <?xml version="1.0" encoding="ISO-8859-1"?> <missions xmlns:xh="http://www.w3.org/1999/xhtml"> <mission> <arret heure="5:30">Corentin Cariou</arret> <arret heure="5:31">Crimée</arret> <arret heure="5:32">Riquet</arret> <arret heure="5:33">Stalingrad</arret> <arret heure="5:35">Louis Blanc</arret> <arret heure="5:36">Château-Landon</arret> <arret heure="5:37">Gare de l'Est</arret> <arret heure="5:39">Poissonnière</arret> <arret heure="5:40">Cadet</arret> <arret heure="5:42">Le Peletier</arret> <arret heure="5:43">Chaussée d'Antin - La Fayette</arret>
Extraction à partir d'un document mal structuré (7/7) Un appel par noeud peut transmettre des paramètres <mission> <xsl:apply-templates select="xh:tbody/xh:tr/xh:td[@headers='station']"> <xsl:with-param name="index-station-heure" select="'mission-1'"/> </xsl:apply-templates> </mission> (...) <xsl:template match="xh:td"> <xsl:param name="index-station-heure" select="'not found'"/> <xsl:variable name="heure" select="key($index-station-heure,.)"/> </xsl:template>
Donner une structure à un document "aplati" (1/7) Toutes les balises sont des éléments vides (sauf pour l'élément racine) <?xml version="1.0" encoding="ISO-8859-1"?> <CATALOG> <PLANT/> <COMMON/>Bloodroot <BOTANICAL/>Sanguinaria canadensis <ZONE/>4 <LIGHT/>Mostly Shady <PRICE/>2.44 <AVAILABILITY/>031599 <COMMON/>Columbine <BOTANICAL/>Aquilegia canadensis
Donner une structure à un document "aplati" (2/7) Structure du document "aplati" CATALOG PLANT COM BOT ZONE 4 PLANT Bloodroot Sanguinaria Canadensis
Donner une structure à un document "aplati" (3/7) Structure souhaitée CATALOG PLANT PLANT COM BOT ZONE Bloodroot 4 Sanguinaria Canadensis
Donner une structure à un document "aplati" (4/7) Méthode : créer des relations "clé/noeud indexé" qui correspondent aux futures relations "élément père/élément fils" clé CATALOG noeud indexé PLANT COM BOT ZONE 4 PLANT Bloodroot Sanguinaria Canadensis
Donner une structure à un document "aplati" (5/7) Les clés sont des chaînes de caractères Utiliser les identifiants des noeuds clé CATALOG noeud indexé PLANT COM BOT ZONE 4 PLANT Bloodroot Sanguinaria Canadensis
Donner une structure à un document "aplati" (6/7) <xsl:key name="parent-to-child" match="PLANT" use="generate-id(..)"/> match="CATALOG/*[local-name()!='PLANT']" use="generate-id(preceding-sibling::PLANT[1])"/> (...) <xsl:template match="CATALOG"> <xsl:copy> <xsl:apply-templates select="key('parent-to-child', generate-id(.))"/> </xsl:copy> </xsl:template>
Donner une structure à un document "aplati" (7/7) <xsl:template match="PLANT"> <xsl:copy> <xsl:apply-templates select="key('parent-to-child', generate-id(.))"/> </xsl:copy> </xsl:template> <xsl:template match="CATALOG/*[local-name()!='PLANT']"> <xsl:value-of select="normalize-space(following-sibling::text()[1])"/>
Résultat <?xml version="1.0" encoding="ISO-8859-1"?> <CATALOG> <PLANT> <COMMON>Bloodroot</COMMON> <BOTANICAL>Sanguinaria canadensis</BOTANICAL> <ZONE>4</ZONE> <LIGHT>Mostly Shady</LIGHT> <PRICE>2.44</PRICE> <AVAILABILITY>031599</AVAILABILITY> </PLANT> <COMMON>Columbine</COMMON> <BOTANICAL>Aquilegia canadensis</BOTANICAL> <ZONE>3</ZONE> <PRICE>9.37</PRICE>
Produire plusieurs documents (1/3) Un index alphabétique des plantes en XHTML avec des liens vers une 2e page XHTML pour les entrées du catalogue <xsl:template match="jr:CATALOG"> <xsl:result-document href="index.xhtml"> <html> (...) <body> <h1>Plant Index</h1> <div class="index"> <xsl:apply-templates select="jr:PLANT" mode="index"> <xsl:sort/> </xsl:apply-templates> </div> </body> </html> </xsl:result-document>
Produire plusieurs documents (2/3) <xsl:result-document href="plant_catalog_jr.xhtml"> <html> <head> <link href="plant-CSS/plant.css" type="text/css" rel="stylesheet"/> <title>Plant Catalog</title> </head> <body> <h1>Plant Catalog</h1> <xsl:apply-templates select="jr:PLANT" mode="catalogue"/> </body> </html> </xsl:result-document> </xsl:template>
Produire plusieurs documents (3/3) <xsl:template match="jr:PLANT" mode="index"> <a href="plant_catalog_jr.xhtml#{generate-id()}"> <xsl:value-of select="jr:COMMON"/> </a> <br/> </xsl:template> <xsl:template match="jr:PLANT" mode="catalogue"> <hr/> <table class="catalog"> <tr> <td class="cell"> <a name="{generate-id()}"/> <h2><xsl:value-of select="jr:COMMON"/></h2>
Résultat : l'index <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns:jr="http://igm.univ-mlv.fr/~laporte/jardinerie" xmlns="http://www.w3.org/1999/xhtml"> <head> <link href="plant-CSS/plant.css" type="text/css" rel="stylesheet"/> <title>Plant Index</title> </head> <body> <h1>Plant Index</h1> <div class="index"> <a href="plant_catalog_jr.xhtml#d1e276">Adder's-Tongue</a> <br/> <a href="plant_catalog_jr.xhtml#d1e292">Anemone</a>
Résultat : le catalogue <body> <h1>Plant Catalog</h1> <hr/> <br/> <table class="catalog"> <tr> <td class="cell"> <a name="d1e3"/> <h2>Bloodroot</h2> <i>Sanguinaria canadensis</i> <p>4</p> <p>Mostly Shady</p> <p>031599</p> <b>2.44</b> </td>
Analyser du texte (1/2) Combien de fois "murder" apparaît-il dans bergman.xml ? <xsl:template match="/"> <xsl:variable name="occurrences"> <xsl:analyze-string select="." regex="[mM]urder"> <xsl:matching-substring> <one-occ/> </xsl:matching-substring> </xsl:analyze-string> </xsl:variable> <xsl:message> <xsl:value-of select="count($occurrences/one-occ)"/> occurrences </xsl:message> </xsl:template>
Analyser du texte (2/2) analyze-string découpe le texte en tokens correspondant et ne correspondant pas au motif donné On construit un arbre dans une constante On compte des noeuds dans l'arbre <xsl:variable name="occurrences"> <xsl:analyze-string select="." regex="[mM]urder"> <xsl:matching-substring> <one-occ/> </xsl:matching-substring> </xsl:analyze-string> </xsl:variable> <xsl:message> <xsl:value-of select="count($occurrences/one-occ)"/> occurrences </xsl:message>