1 Introduction à XSLT - cours 4 Éric Laporte Institut Gaspard-Monge Université Paris-Est...

Preview:

Citation preview

1

Introduction à XSLT - cours 4

Éric Laporte

Institut Gaspard-Monge

Université Paris-Est Marne-la-Vallée

2

Sommaire

Regrouper des entrées4

Introduire des références 12Produire un index

22Extraire des informations d'un document mal structuré 37Rendre explicite une structure implicite 44Produire plusieurs documents en même temps 52Analyser du texte 57

3

4.                     Objectifs5.                      Grouper par albums (1/4)6.                      Résultat7.                      Grouper par albums (2/4)8.                     Grouper par albums (3/4)9.                      Grouper par albums (4/4)10.                    Résultat11.                    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ésultat15.                    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ésultat22.                    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)

30.                    Expressions relatives31.                    Expressions relatives32.                    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ésultat53.                    Produire plusieurs documents (1/3)54.                    Produire plusieurs documents (2/3)55.                    Produire plusieurs documents (3/3)56.                    Résultat : l'index57.                    Résultat : le catalogue58.                    Analyser du texte (1/2)59. Analyser du texte (2/2)

4

Objectifs

Réorganiser la structure d'un document XMLCertains 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 choseAjouter des informations redondantes (exemple : un

index alphabétique)

5

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> </xsl:template>

6

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>

7

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>

8

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 courantLa 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>

9

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>

10

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>

11

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>

12

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'/>

13

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>

14

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> <BOTANICAL> <GENUS>Caltha</GENUS> <SPECIES>palustris</SPECIES> </BOTANICAL>

15

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>

16

Introduire des référencesà d'autres entrées (3/5)

CATALOG

PLANT

BOTANICALCOMMON

BloodrootSanguinaria Canadensis

PLANT

...

ZONE LIGHT

4Mostly Shady

...

noeud à indexer

clé d'indexation

<xsl:strip-space elements="*"/> <xsl:key name="botanical-to-plant" match="jr:PLANT" use="jr:BOTANICAL"/>

17

Introduire des référencesà d'autres entrées (4/5)

CATALOG

PLANT

BOTANICALCOMMON

BloodrootSanguinaria Canadensis

PLANT

...

ZONE LIGHT

4Mostly Shady

...

noeud indexé

clé d'indexation

<xsl:variable name="meme-nom" select="key('botanical-to-plant', jr:BOTANICAL)"/>

18

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 à indexerConvertie 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

19

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">

20

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>

21

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"> <GENUS>Erythronium</GENUS> <SPECIES>americanum</SPECIES> </BOTANICAL> <ZONE>4</ZONE>

22

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

<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>

<CATALOG xmlns="http://igm.univ-mlv.fr/~laporte/jardinerie"> <PLANT id="1"> <COMMON>Bloodroot</COMMON>

23

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 ;

24

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> <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>

25

Index des horaires de métro (3/7)

tbody

tr

tdtd

a Fort d'Aubervilliers

tr

...

td td

5:30

...

noeud à indexer

clés d'indexation

td

5:34

26

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>

27

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>

28

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>

29

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

tdtd

a Fort d'Aubervilliers

td td

5:30

...

noeud à indexer

clés d'indexation

td

5:34

30

. ../*

..

*@

../../*

*/*

@*

31

preceding::* following::*

descendant::*

ancestor::*

self::*

following-sibling::*preceding-sibling::*

parent::*

child::*@attribute::*

32

Axes Xpath (1/6)

<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

tdtd

a Fort d'Aubervilliers

td td

5:30

...

noeud à indexer

clés d'indexation

td

5:34

33

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::*[.=':']

34

Axes (3/6)

Certaines expressions n'ont aucune abréviation possibleparent::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::*

35

Axes (4/6)

Parenthésage interditchapitre/section|chapitre/figure OKchapitre/(section|/figure) interdittr[@class='blue']|td[@class='blue'] OK(tr|td)[@class='blue'] interditdescendant::*|self::* OK(descendant|self)::* interditdescendant-or-self::* OKancestor-or-self::* OK

36

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()[.=':']

37

Axes (6/6)

Ordre d'une liste de noeudsSert à évaluer position()

Pour la plupart des axesOrdre 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

38

Extraction à partir d'un documentmal structuré (1/7)

ligne7.xml est structuré pour la visualisation uniquementExtraire les missions des premiers et derniers trains (liste des stations avec les heures de passage)

39

Extraction à partir d'un documentmal structuré (2/7)

ligne7.xml est structuré pour la visualisationOn 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> <td id="place_d_italie" headers="station" class="gauche"> <strong>Place d'Italie</strong> </td> <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>

40

Extraction à partir d'un documentmal structuré (3/7)

Indexer les horaires par les noms des stations

tr

tdtd

a Fort d'Aubervilliers

td td

5:30

...

noeud à indexer

clé d'indexation

td

5:34

41

Extraction à partir d'un documentmal 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]" use="preceding-sibling::xh:td[@headers='station']"/>

42

Extraction à partir d'un documentmal 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>

43

Extraction à partir d'un documentmal structuré (6/7)

<?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>

Résultat

44

Extraction à partir d'un documentmal 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>

45

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<PLANT/><COMMON/>Columbine<BOTANICAL/>Aquilegia canadensis

46

Donner une structureà un document "aplati" (2/7)

Structure du document "aplati"

PLANT

CATALOG

COM BOT ZONE PLANT

Bloodroot

Sanguinaria Canadensis

4

47

Donner une structureà un document "aplati" (3/7)

Structure souhaitée

PLANT

CATALOG

COM BOT ZONE

PLANT

Bloodroot

Sanguinaria Canadensis

4

48

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"

PLANT

CATALOG

COM BOT ZONE PLANT

Bloodroot

Sanguinaria Canadensis

4

clé

noeudindexé

49

Donner une structureà un document "aplati" (5/7)

Les clés sont des chaînes de caractèresUtiliser les identifiants des noeuds

PLANT

CATALOG

COM BOT ZONE PLANT

Bloodroot

Sanguinaria Canadensis

4

clé

noeudindexé

50

Donner une structureà un document "aplati" (6/7)

<xsl:key name="parent-to-child" match="PLANT" use="generate-id(..)"/> <xsl:key name="parent-to-child" 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>

51

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:copy> <xsl:value-of select="normalize-space(following-sibling::text()[1])"/> </xsl:copy> </xsl:template>

52

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> <PLANT> <COMMON>Columbine</COMMON> <BOTANICAL>Aquilegia canadensis</BOTANICAL> <ZONE>3</ZONE> <LIGHT>Mostly Shady</LIGHT> <PRICE>9.37</PRICE>

53

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>

54

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>

55

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/> <br/> <table class="catalog"> <tr> <td class="cell"> <a name="{generate-id()}"/> <h2><xsl:value-of select="jr:COMMON"/></h2>

56

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>

57

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>

58

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>

59

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 constanteOn 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>

Recommended