Diapositive 1
Download
Report
Transcript Diapositive 1
XSLT : XML Stylesheet
Language Transformation
Une introduction à XSLT pour
l'analyse de corpus
Sylvain Loiseau <[email protected]>
Introduction
2
• Note : pour apprendre ce langage il est
indispensable de disposer d’un processeur
et de tester et modifier les exemples du
diaporama.
3
« Feuille de style »
et « transformation »
• Le programme XSLT est appelé une « feuille de
style »
• La feuille de style est fournie, avec un document
XML, à un programme (un « processeur XSLT »)
• Le processeur « transforme » le document en
fonction des instructions de la feuille de style et
produit en sortie un nouveau document.
XSLT
XML
Processeur XSLT
XML / HTML / texte
4
Principe de la transformation XSLT
• La feuille de style décrit des règles de
transformation que le processeur applique au
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 (tri,
décompte, etc.) et ajouter des éléments nouveaux.
5
Le processeur transforme le
document en un autre
Feuille de style
XSLT :
règles de la
transformation
Racine
teiHeader
Document
XML
source
truc
fileDesc
title
Text
machin
Transformation
Text
Text
Processeur
Document
XML
produit
6
Exemples d’utilisation
• Rechercher des éléments du corpus
– En utilisant toutes les propriétés du document
• Composer des sous corpus
– Texte sans les <note>, seulement les <note>…
• Quantifications
– Pourcentage des <foreign> dans les <note>
• Convertir d'un format à l'autre
– XML vers Hyperbase, Unitexte, sans balise, etc.; ou vers
des formats de lecture : HTML, PDF, Word, etc.
• Maintenance et enrichissement du corpus
– Possibilité (limitée) d’ajouter de l’information
7
Intérêt du couple XML/XSLT
• On ne maintient pas différentes versions
du corpus pour les différents formats ou
les différents sous-corpus
• On peut appliquer les mêmes feuilles de
style à plusieurs corpus.
• Pas de programmation
8
Objectif du diaporama
• Introduction aux principes et aux
principales fonctions de XSLT
• Application pour l’utilisation de corpus.
• Proposer différentes approches pour les
principales tâches : extraire des
informations, calculer des valeurs
numériques, convertir vers d’autres
formats, lister des valeurs, et ajouter de
l’information.
9
Une première feuille de style
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<p>Hello, world</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Préfixé par « xsl: » = des
instructions XSLT, ici
d’organisation de la feuille
de style
Texte non-préfixé par
« xsl: » : recopié
littéralement en sortie
10
Résultat :
<html>
<body>
<p>Hello, world</p>
</body>
</html>
• 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: »)
• Cette feuille de style ne contient que des éléments « littéraux »
: elle n’extrait aucune information du document
• Ici les balises rajoutées sont du HTML : à partir du document
on génère une page HTML. Le résultat de la transformation
peut être ouvert et affiché dans un navigateur. (Fichier->Ouvrir
dans Internet Explorer) Ce n’est pas obligatoire : on peut aussi
écrire des balises non-HTML, ou ne mettre aucune balise dans
11
le résultat.
Pour résumer
• Une feuille de style est un document XML
– L'élément racine est xsl:stylesheet avec
deux attributs obligatoires
– La feuille de style contient un élément
xsl:template
• 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
12
Extraire des informations
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:template match="/">
<html><body>
<p>Titre du corpus :
<xsl:value-of select =
"/teiCorpus.2/teiHeader/fileDesc/titleStmt/title"/>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
14
L'instruction xsl:value-of
<xsl:value-of select="/TEI.2/.../title"/>
Remplacer cette instruction
par le texte…
… trouvée à cet endroit
La valeur de l'attribut select est une
expression XPath : elle désigne un endroit
du document où aller chercher le texte.
15
"/TEI.2/teiHeader/fileDesc/titleStmt/title"
Document
/
PI
<?xml version=“1.0”?>
Element
TEI.2
Element
teiHeader
Element
…
Element
fileDesc
Text
Element
title
Text
Element
…
Element
…
Text
Text
Text
16
<xsl:value-of select="/corpus/text/p/name"/>
Document
/
PI
<?xml version=“1.0”?>
Element
corpus
Bien qu’il y ait plusieurs p, un
seul chemin satisfait
entièrement à l’expression (un
seul p a un élément name)
Element
p
Element
text
Element
p
Text
Element
name
Text
Element
p
Element
p
Text
Text
Text
17
XPath
• XPath est une autre recommandation, comprise
dans XSLT
• XPath remplit la fonction de "sélectionner",
"pointer" sur des éléments du document, tandis
que XSLT organise, trie, etc.
• XPath retourne des nœuds de l'arborescence,
par exemple des balises, des attributs, des
nœuds textes.
• XPath permet de désigner les propriétés XML
(nom des balises et attribut, contexte, ordre…)
18
xsl:value-of convertit le nœud en texte :
supprime les balises incluses
Instruction XSLT …
<xsl:value-of select="p" />
… sur ce document XML
<p>du texte et <hi
rend="italics">d'autres</hi> éléments</p>
XPath retourne un « nœud », XSLT converti en texte :
du texte et d'autres éléments
19
Si plusieurs éléments correspondent ?
<xsl:value-of select="/TEI.2/text/body/p"/>
• Il y a sans doute beaucoup de p qui
correspondent à ce chemin.
• XPath les retourne tous, mais la fonction
xsl:value-of ne sélectionne que le
premier pour l'afficher.
20
xsl:for-each
• Si on veut traiter tous les nœuds retournés
par l'expression XPath, il faut utiliser
xsl:for-each
<xsl:for-each select="expression XPath">
On traite une à une les valeurs trouvées
</xsl:for-each>
21
<xsl:for-each select="/teiCorpus.2/TEI.2/text/p">
<para><i><xsl:value-of select="." /></i></para>
</xsl:for-each>
<p>Premier <hi rend="italics">paragraphe</hi>
éléments</p>
<p>Second paragraphe</p>
<p>Troisième paragraphe</p>
<para><i>Premier éléments</i></para>
<para><i>Second paragraphe</i></para>
<para><i>Troisième paragraphe</i></para>
22
<xsl:for-each select="/teiCorpus.2/TEI.2/text/p">
<p><i><xsl:value-of select="." /></i></p>
</xsl:for-each>
Element
TEI.2
Element
text
Element
p
Element
p
Text
Element
name
Text
Element
p
Element
p
Text
Text
Text
23
• 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 qu'un seul élément, ou zéro, la boucle
serait exécutée une ou zéro fois.
- À chaque passage on traite un des nœuds trouvés,
qui devient le "nœud contexte" durant ce passage et
peut être désigné par «.».
- Dans le contenu de la boucle, on peut se déplacer à
nouveau dans l'arborescence, mettre un élément
littéral, etc.
24
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html><body>
<p>Titre du corpus :
<xsl:value-of select =
"/teiCorpus.2/teiHeader/fileDesc/titleStmt/title"/>
</p>
<xsl:for-each select="/teiCorpus.2/TEI.2">
<p>Titre :
<xsl:value-of select="teiHeader/fileDesc/titleStmt"/>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
25
<xsl:for-each select="/teiCorpus.2/TEI.2">
Element
…
Element
TEI.2
Element
TEI.2
Element
TEI.2
…
Element
…
Element
…
Element
title
…
Element
TEI.2
…
A chaque itération on
applique une nouvelle
recherche XPath
Element
…
Text
26
<xsl:value-of select="teiHeader/fileDesc/titleStmt/title"/>
Le 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 "."
– C'est à partir du nœud contexte que sont évaluées les
expressions XPath qui ne commencent pas par "/" :
select="teiHeader/fileDesc/titleStmt"
On désigne, par rapport au nœud contexte, un endroit
de la sous-arborescence. On aurait pu écrire aussi :
select="./teiHeader/fileDesc/titleStmt"
27
Une utilisation de xsl:for-each :
faire une table des matières du corpus
• On ne sait pas combien de textes ni de
titres de niveau 1, 2, etc., il peut y avoir
• Il faut traiter tous les textes, et dans
chaque texte traiter les niveaux 1, dans
chaque niveau 1 traiter les niveaux 2, etc.
• On peut donc imbriquer des boucles
xsl:for-each
28
Une table des matières (1)
• On extrait le titre de chaque texte dans le
corpus :
<xsl:for-each select="/teiCorpus.2/TEI.2">
<p>Titre :
<xsl:value-of
select="teiHeader/fileDesc/titleStmt/title"/>
</p>
<hr />
</xsl:for-each>
Cf. ci-joint le fichier TableDesMatieres.xsl
29
Une table des matières (2)
• A l'intérieur du for-each, à chaque itération, le
nœud contexte est donc l'élément TEI.2 traité
• On peut lancer une nouvelle boucle, dans la
première, pour chercher les titres de niveaux 1
dans cet élément TEI.2
L’expression XPath ne
<xsl:for-each select="/teiCorpus.2/TEI.2"> commence pas par « / »
: text est recherché
<p>Titre :
parmi les enfants du
<xsl:value-of select=
"teiHeader/fileDesc/titleStmt/title"/> nœud contexte (le TEI.2
traité)
</p>
<xsl:for-each select="text/body/div[@type = '1']">
<h1><xsl:value-of select="head"/></h1>
</xsl:for-each>
<hr />
Par rapport au nouveau contexte (div),
</xsl:for-each>
30
on désigne le premier enfant head
select="text/body/div[@type = '1']"
1.
Ce qui est entre crochets est un prédicat : permet
de filtrer les éléments sélectionnés.
2. @ permet de désigner un attribut.
3. Respecter l’alternance guillemets / apostrophes
<xsl:value-of select="head"/>
Sélectionne le premier élément head directement en
dessous de div. On aurait pu écrire aussi :
<xsl:value-of select="./head"/>
31
Une table des matières (3)
<xsl:for-each select="/teiCorpus.2/TEI.2">
<p>Titre : <xsl:value-of
select="teiHeader/fileDesc/titleStmt/title"/></p>
<xsl:for-each select="text/body/div[@type = '1']">
<h1><xsl:value-of select="./head"/></h1>
<xsl:for-each select="div[@type = '2']">
<h2><xsl:value-of select="./head"/></h2>
<xsl:for-each select="div[@type = '3']">
<h3><xsl:value-of select="./head"/></h3>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
<hr />
</xsl:for-each>
32
Classer avec xsl:sort
<xsl:for-each select="/teiCorpus.2/TEI.2">
<xsl:sort
select=“teiHeader/fileDesc/titleStmt/title"
order="ascending"/>
<!-- les textes sont classés par leur titre-->
<xsl:value-of select="." />
</xsl:for-each>
Les éléments sont extraits avec for-each ; 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
33
textes sont donc classés par leur titre).
Ajouter un index
• xsl:number permet de retourner un
nombre correspondant à l'index de
l'élément dans le node set.
<xsl:for-each select="/teiCorpus.2/TEI.2">
<xsl:number value="position()" format="1. "/>
<xsl:value-of select="." />
</xsl:for-each>
1. Premier titre
2. Second Titre
3. Etc
34
xsl:output
• Indiquer le jeu de caractères de la sortie avec
<output encoding='...'>
• Indiquer le type de sortie (text, XML, HTML) avec
mode (Permet d’ajouter le prologue XML ou HTML)
<xsl:stylesheet version="1.0"
xmlns:xsl=
"http://www.w3.org/1999/XSL/Transform">
<xsl:output
encoding="iso-8859-1"
mode="html" />
35
Résumé XPath
XPath permet d’écrire des « chemins
XML » mais également d’utiliser des
fonctions et des opérateurs.
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) :
le nom d’un élément, attribut, etc.
• Optionnellement le node set peut avoir (3) un prédicat (à
droite) et (4) un axe (à gauche)
• L'expression retourne un sac de nœuds : les nœuds qui
correspondent au dernier nœud asserté – si elle en trouve.
"/TEI.2/text/body/div[@type='intro']/head"
37
(1) les étapes
• Le slash indique la relation parent / enfant
• Un double slash indique la relation parent /
descendants (à toute profondeur dans la
hiérarchie).
/TEI.2[1]/text/body//name[@type='np']
– 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.
38
Exemples
teiCorpus.2/TEI.2/teiHeader
//TEI.2[1]//p
• 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 :
– //TEI.2/text//div/p
Les p directement en dessous de tous les div
– //TEI.2/text/div//p
Tous les p en dessous de div directement en dessous de text
• Avec //TEI.2/text//div//p chaque p est
sélectionné une fois dans le sac de nœuds résultant, même
si plusieurs div 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.
39
(2) : les node tests
• Chaque étape comprend un node test
• Le nœud cherché peut être une balise, un
attribut (@nom) ou un nœud texte (text())
• Existent également des valeurs génériques : *
(tout élément), @* (tout attribut) , node() (tout
nœud : texte, élément, attribut, PI, comment,…)
• Le point "." indique le contexte actuel
• Le double point ".." permet de remonter d'un
niveau dans l'arborescence.
40
Exemples
•
•
•
•
•
//*[@rend = 'italics']/text()
teiCorpus.2/TEI.2[1]/teiHeader
//p[../liste]
//p/@id : retourne la valeur de l’attribut
Ne pas confondre un nœud texte et le texte contenu :
– /TEI.2/text/front
Retourne tout le texte contenu, sans les balises
– /TEI.2/text/front/text()
Retourne les nœuds texte directement enfants de front, avec
value-of retourne uniquement le premier nœud :
probablement un retour chariot…
– TEI.2/text/front/@id/text()
Ne retourne rien : il n'y a pas de nœud texte descendant
41
d'un attribut. (@id retourne déjà la "valeur")
(3) : les prédicats
• Chaque étape peut comprendre un prédicat, qui est une
expression XPath entre crochets placée après le node test.
– Ex. //div[@type='intro'] sélectionne les div ayant un attribut
@type avec la valeur 'intro'
• Le prédicat permets de filtrer les nœuds en ajoutant des
conditions.
• L’expression XPath dans le prédicat peut avoir deux
valeurs : vraie ou fausse.
• L’expression XPath 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 « = »
– Ex. //p[name] sélectionne tous les p contenant un élément enfant
« name ». p est le contexte de l’expression XPath « name ». 42
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 du dernier nœud d’un
sac de nœuds et le numéro 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].
43
Exemples
<xsl:for-each select="/teiCorpus.2//hi[@rend = ‘italics’]">
<!-- tous les tags hi avec un attribut rend = italics -->
</xsl:for-each>
<xsl:for-each select="//TEI.2[1]/text/p[name/@id]">
<!-- tous les p qui ont un enfant name qui a un attribut id -->
</xsl:for-each>
<xsl:for-each select="//TEI.2[1]/text/p [not(position()=last())]">
<!– tous les p qui ne sont pas les derniers parmi les éléments ayant le même
parent -->
</xsl:for-each>
<xsl:for-each select="//TEI.2[1]/text/p[position() != last())]">
<!-- autre notation -->
</xsl:for-each>
<xsl:for-each select="//TEI.2[1]/text/p[position() > 1]">
<!-- tous les p sauf le premier -->
</xsl:for-each>
44
<xsl:value-of
<xsl:value-of
<xsl:value-of
<xsl:value-of
<xsl:value-of
<xsl:value-of
<xsl:value-of
select="text/p[3]"/>
select="text/p[name]"/>
select="text/p/name"/>
select="text[p/name]/p[3]"/>
select="text/p[name/@n]"/>
select="text/p[not(text())]"/>
select="text/p[last()]"/>
<xsl:value-of select="text/p[not(position() = last())]"/>
Element
text
Element
p
Element
p
Text
Element
name
n='8'
Text
id='p5'
Element
p
Element
p
Text
Text
(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 de l'étape précédente, ou
parmi les descendants avec //.
• Il est donc impossible dans cette notation
d'indiquer un chemin qui remonte vers les
autres directions : ancêtres, parents,
descendants, ou frères du nœud contexte :
46
XML, une histoire
de famille
Document
/
PI
<?xml version=“1.0”?>
Element
corpus
Ancêtres
Element
text
Parent
Frêres
Element
p
Element
p
Text
Element
name
Text
Element
p
Element
p
Text
Text
Text
Enfants
Descendants
47
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
Recherche le premier div parmi les
ascendants
Remonte au TEI.2 ascendant,
–Select="./ancestor::TEI.2/teiHeader puis descend à son enfant direct
teiHeader
–select="./ancestor::div"
–Following-sibling::node() | Sélectionne n’importe quel type de nœud
descendant du même père, soit à droite
preceding-sibling::node()
48
sinon à gauche
Document
/
PI
<?xml version=“1.0”?>
Element
FitnessCenter
Ancêtres
Element
Member
Element
Name
Text
Jeff
Element
Phone
Element
Phone
Frêre précédent
Parent
Element
FavoriteColor
Frêres Suivants
Element
Name
Text
555-4321
Text
lightgrey
Enfant
Text
Jeff
Descendants
49
Document
/
PI
<?xml version=“1.0”?>
Element
FitnessCenter
ancêtre
Element
Name
Element
Phone
Frêre précédent
Text
Jeff
ancestor::* sélectionnera tous
les ancêtres, c’est à dire :
- Member
- FitnessCenter
Element
Member
Element
Phone
Element
FavoriteColor
Text
555-4321
Text
lightgrey
Frêres suivants
Text
555-1234
preceding-sibling::*
sélectionnera tous les frêres à
gauche, c’est à dire :
- Name
following-sibling::*
sélectionnera tous les frêres à
droite, c’est à dire :
50
- Phone
- FavoriteColor
Document
/
PI
<?xml version=“1.0”?>
descendants
Element
FitnessCenter
Element
Member
Element
Name
Text
Jeff
Element
Phone
Element
Phone
Element
FavoriteColor
Text
555-1234
Text
555-4321
Text
lightgrey
À partir de FitnessCenter, descendant::*
sélectionnera tous les descendants, c’est à dire :
- Member
- Name
- Phone, etc
51
Liste des axes
• ancestor: sélectionne tous les ancestors
• ancestor-or-self: sélectionne tous les le noeud 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 noeud courant plus tous ses
descendants
• following: sélectionne tout ce qui suit le noeud 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 noeud courant dans le
document
• preceding-sibling: sélectionne tous les frêres à gauche
• self: sélectionne le noeud courant
52
Exemples
53
• L'axe child:: est l'axe par défaut, "@«
abrège l'axe attribute::, "//" abrège
descendant-or-self::, "." abrège l'axe self::
et ".." l'axe parent::.
54
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 :
< > = <= >= !=
55
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.
impossible : @type[1] ou //*[@type[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"
56
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="TEI.2[1]//sourceDesc">
<p>
Le premier texte du corpus
a un élément sourceDesc
</p>
</xsl:if>
58
Exemples de xsl:if
<xsl:for-each select="name">
<xsl:if test="@type='person'">
<xsl:value-of select='.'>
</xsl:if>
</xsl:for-each>
Ici c'est l'équivalent de :
<xsl:for-each select="name[@type='person']">
<xsl:value-of select='.'>
</xsl:for-each>
59
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 trouve des nœuds.
– Elle retourne faux si elle ne trouve rien.
60
xsl:choose
• Exprimer des alternatives avec xsl:choose. Le
premier élément when dont le test est positif est
exécuté.
<xsl:choose>
<xsl:when test='expression XPath'>
[action]
</xsl:when>
<xsl:when test='expression XPath'>
[action]
</xsl:when>
<xsl:otherwise>
[action]
</xsl:otherwise>
</xsl:choose>
61
...
<xsl:template match="/">
...
<xsl:for-each select="/teiCorpus.2/TEI.2">
<p>Titre : <xsl:value-of
select="teiHeader/fileDesc/titleStmt/title"/></p>
<xsl:if select="teiHeader/fileDesc/sourceDesc">
<p>
Source du texte :
<xsl:if select=".//author">
<xsl:value-of select="." />
</xsl:if>
<xsl:if select=".//docDate">
<xsl:text> (</xsl:text>
<xsl:value-of select="." />
<xsl:text>), </xsl:text>
<xsl:if>
<xsl:if select=".//title">
<i><xsl:value-of select="title" /></i>
<xsl:if>
</p>
</xsl:if>
...
62
Extraire une sous-chaîne
• Dans un nœud texte, on peut extraire une sous
chaîne.
ex. Extraire la date seule dans "value = "2002""
• Utiliser la fonction XPath "substring-after()"
qui prend deux arguments
– La chaîne source
– La chaîne à partir de laquelle sélectionner le texte.
substring-after(chaîne, pattern)
63
Exemple
<xsl:if test="docDate">
<xsl:text> (</xsl:text>
<xsl:value-of select=
"substring-after(docDate, '= ')" />
<xsl:text>), </xsl:text>
<xsl:if>
docDate
value = "2002"
substring-after(docDate, ‘= ’)
"2002"
64
• 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
sont nombreuses mais rudimentaires:
65
Fonctions sur des chaînes
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 sur les chaînes 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(., ‘2002')]">
<!-- Sélectionne les noeuds contenant 2002 -->
66
• Exemple d'utilisation : on veut les éléments en
italique, avec 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 si on utilise
select="//*[@rend = 'IT']", qui
recherchera les @rend avec comme valeur
exactement IT.
• contains permet ici de récupérer tous les
italiques
Select="//*[contains(@rend, 'IT')]"
67
• 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.
– Impossible par exemple de s’en servir pour
extraire les phrases en se basant sur la
ponctuation
68
Quantifier
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'])"/>
<xsl:value-of select=
"count(//*[@lang = 'en'])"/>
<xsl:value-of select=
"count(//div/p[1]/*[@ana= 'exemple'])"/>
70
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 ?
71
xsl:variable
• xsl:variable permet de strocker 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 :
Valeur de la variable :
hello
Hello World
72
Stocker une valeur calculée
<xsl:variable name="nbrDiv"
select="count(//div)" />
<xsl:variable name="nbrDiv1"
select="count(//div[@type = '1'])" />
<xsl:variable name="nbrDiv2"
select="count(//div[@type = '2'])" />
Pourcentage de section de niveau 1 :
<xsl:value-of
select="($nbrDiv1 * 100) div $nbrDiv" />
Pourcentage de section de niveau 2 :
<xsl:value-of
select="($nbrDiv1 * 100) div $nbrDiv" />
•Évite de recalculer plusieurs fois count(//div)
73
•Code plus lisible
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.
74
Quelques fonctions arithmétiques
• sum(node set) calcule la somme de toutes les
valeurs présentes dans le node set
• round(numbre) arrondit number à l’entier le plus
proche
– Exemple round(2.3) retourne 2
• Etc.
75
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
76
<xsl:template match="/">
<xsl:variable name="nbrDiv" select="count(//div)" />
<xsl:variable name="nbrDiv1" select="count(//div[@type = '1'])" />
<xsl:variable name="nbrDiv2" select="count(//div[@type = '2'])" />
Pourcentage de section de niveau 1 :
<!– La formule du calcul du pourcentage est confiée à un
template, auquel on transmet des arguments -->
<xsl:call-template name="calculPourcentage">
Appel d’un template
<xsl:with-param name="Nbr1" select="$nbrDiv1"/>
<xsl:with-param name="Nbr2" select="$nbrDiv"/>
xsl:with-param permet
</xsl:call-template>
de transmettre les
Pourcentage de section de niveau 2 :
<!-- etc. -->
<!-- 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>
arguments
xsl:param permet de
nommer les
arguments reçus
77
Utiliser des templates
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…
79
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.
80
• Plutôt que de décrire des opérations, on
dessine un nouvel arbre en indiquant
seulement les points à modifier de l'arbre
existant.
81
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.
82
Comment utiliser les templates ?
• Il suffit, pour l’élément que l’on veut traiter, de lui
faire un élément template avec un @match qui
lui correspond.
– @match peut correspondre à tout nœud : élément,
attribut (avec @) ou texte (avec text()).
– Exemple : un template qui s’appliquera à chaque
élément TEI.2 dans le document :
<xsl:template match="TEI.2">
...
<xsl:template>
83
Exemple : mettre un titre HTML à
chaque texte
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="TEI.2">
<h1>nouveau texte :
<xsl:value-of select=".//titleStmt/title" />
</h1>
<xsl:apply-templates />
</xsl:template>
</xsl:stylesheet>
84
xsl:apply-templates
• Dans l'exemple précédent, applytemplates sert à relancer l'analyse (la
recherche d'un template avec un attribut
match qui correspond) dans la sousarborescence 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 dessous
85
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.
86
Document
/
Le processeur parcours les
éléments dans un ordre prévisible
(les attributs d'un élément dans un
ordre non prévisible)
PI
<?xml version=“1.0”?>
Element
corpus
Element
text
Element
p
Element
p
Text
Element
name
Text
Element
p
Element
p
Text
Text
Text
87
• 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
Idem : s’il n’existe pas de template
pour name, passe aux nœuds enfants
Element
p
Element
p
Text
Element
name
88
• 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 sousarborescence (d’autres templates peuvent être
exécutés), puis le p est fermé
<xsl:template match="name">
M. ***
</xsl:template>
Element
p
Element
p
Text
Toutes les balises name et leur contenu sont remplacés par « M. *** ».
Element
name
89
L’enchâssement
• Dans un template, l’ instructions, xsl:applytemplates 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
90
L'enchâssement (2)
<?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:template>
</xsl:stylesheet>
1. Imprimé en premier
2. Passe à la
descendance, alors que
le template n'est pas fini.
Imprime le texte contenu
dans les éléments sauf p
3. Tous les p sont traités
4. Quand la
descendance est traitée
"remonte" de templates
appelant en templates
appelant et fini chacun.
Cette ligne est donc
91
imprimée en tout dernier
Utilisation de xsl:apply-templates
• On peut mettre plusieurs xsl:apply-templates dans
le même template.
<xsl:template match="/">
<html><body>
<h1>1. les ref</h1>
<xsl:apply-templates select="//xptr">
<h1>2. les id</h1>
<xsl:apply-templates select="//xptr/@id">
</body></html>
</xsl:template>
92
apply-templates : utiliser @select
@select permet de préciser au processeur où reprendre la
recherche de templates
<xsl:template match="/">
<sous-corpus>
<xsl:apply-templates select='teiCorpus.2//text/body//p'/>
</sous-corpus>
</xsl:template>
<xsl:template match="p">
<item><xsl:value-of select="." /> </item>
</xsl:template>
Voir les deux schémas suivants…
Ici on évite de recopier les
header, front et back, en
passant directement aux p
93
select indique où relancer
l'analyse dans l'arborescence.
Le processeur ne cherche pas
de templates pour les
descendants de /, par exemple il
saute par-dessus un teiHeader.
Document
/
<xsl:template match="/">
…
<apply-template select =‘xx/xx//p'
PI
<?xml version=“1.0”?>
Element
corpus
Element
text
Element
p
Element
p
Text
Element
name
Text
Element
p
Element
p
Text
Text
Text
94
Pour chacun des fragments
désignés par select, la
recherche de templates et le
parcours dans la sousarborescence reprend
<xsl:template match=“p">
Element
p
Element
p
Text
Element
name
Element
p
Element
p
Text
Text
Text
Text
95
• @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, voire relancer
l'analyse à la racine avec un select="/" qui
fait boucler indéfiniment.
• Note : par défaut, un xsl:apply-templates
contient donc un @select="node()" qui le fait
sélectionner ses enfants
96
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>
• 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 noeuds
de type texte et passe aux enfants pour les
autres types de nœuds.
97
select : exemple d'utilisation
• On veut recopier le texte du corpus sans
balises, et sauter les header du corpus et
des textes.
• Dans ce cas de figure, la majorité du corpus
est recopié, et c'est seulement un tag dont le
contenu est à exclure. La méthode la plus
économique consiste donc à laisser le
processeur recopier par défaut, et indiquer le
tag à exclure.
98
Méthode 1
• select permet de paramétrer le chemin du
processeur pour exclure les headers
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="teiCorpus.2">
<!-- on saute le header du corpus en passant directement aux TEI.2 -->
<xsl:apply-templates select='//TEI.2'/>
</xsl:template>
<xsl:template match="TEI.2">
<!-- dès qu'on arrive à un TEI.2, on fait sauter le header des TEI.2
en passant au texte -->
<xsl:apply-templates select='text'/>
</xsl:template>
99
</xsl:stylesheet>
Méthode 2
• Plutôt que d'indiquer au processeur des chemins
à parcourir qui excluent les headers, 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="teiHeader">
<!– le template ne contient rien : ni action, ni relance du
processeur avec apply-templates. Le contenu est donc abandonné -->
</xsl:template>
</xsl:stylesheet>
100
La clef : les templates par défaut
• Pourquoi, par défaut, le processeurs descend dans
l'arborescence et imprime les noeuds 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 noeud traité
<xsl:template match=“/ | *”>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match=“text()”>
<xsl:value-of select=“.”/>
</xsl:template>
Correspond à la racine (/) ou (|) à tout
element (*). Action = avancer le processeur
aux enfants (incluant élément, attribut et
noeud texte : apply-template à par défaut
@select=“node()”), et leur appliquer les
templates.
Correspond à tout noeud texte.
Action = imprimer son contenu
101
Quand plusieurs templates
peuvent s’appliquer…
• pourquoi le processeur applique
<xsl:template match="TEI.2">
et non le template par défaut
<xsl:template match="/ | *">,
alors que les deux correspondent ?
• 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 sauf...
@match="p[1]" s’applique à tous les aînés des fratries.
102
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
noeuds textes.
103
Exemple de modification des
templates par défaut
• On veut extraire du corpus seulement le
contenu des nœuds note.
• Dans ce cas de figure la majorité du corpus
est à exclure, seulement un tag est à
conserver.
• Comme dans l'exemple précédent 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
104
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 note
<?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="//note">
</xsl:template>
</xsl:stylesheet>
105
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="note">
<note><xsl:value-of select='.'/></note>
</xsl:template>
</xsl:stylesheet>
106
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
éléments enfants / éléments 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.
107
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 l'approche la plus économique pour
décrire une transformation de l’arborescence
source en une arborescence cible.
108
Exemple
• Conversion TEI -> Hyperbase
• Conversion TEI -> HTML
– permet de lire le fichier à l'écran avec un
navigateur internet, de l'ouvrir avec Microsoft
Word pour l'imprimer ou le convertir dans le
format Word.
Cf. fichiers joints
109
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="1206-2002">), les classer par correcteur sans
les connaître à l'avance.
111
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.
112
<xsl:key
name="grouperParResp"
match="//corr"
use="@resp"
/>
On recherche les tags corr
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>
Clefs
DB
CF
Nœuds collectés
<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>
113
• 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.
114
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>
Appliqué à l'exemple
précédent :
Texte
Texte
Texte
Texte
d'origine
corrigé
d'origine
corrigé
:
:
:
:
désaisissant
dessaisissant
desine
115
dessine
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.
116
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 noeuds doublons
du noeud traité.
•key(Langues', .)[1] retourne le premier élément du groupe
•generate-id retourne un identifiant unique pour un noeud. L'id
du noeud contexte doit être le même que l'id du premier noeud du
groupe des noeuds doublons.
• On sélectionne uniquement le premier noeud de chaque groupe,
donc un noeud par groupe.
117
• 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])]">
<tr>
<td><xsl:value-of select="@lang" /></td>
<td><xsl:value-of select="count(key('Langue',
@lang))"/>
</td>
</tr>
</xsl:for-each>
</table>
118
• @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.
119
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.
121
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>
122
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:template>
123
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éé.
124
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.
125
<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>
<xsl:template match="note">
</xsl:template>
</xsl:template>
Cf. ci-joint "ajout.xsl"
126
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.
128
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 »
129