« Tutoriel XSLT débutant » : différence entre les versions

De EduTech Wiki
Aller à la navigation Aller à la recherche
mAucun résumé des modifications
m (modification d'un petit paragraphe et des accords)
 
(137 versions intermédiaires par 16 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
{{en construction}}
{{tutoriel
|fait_partie_du_cours=XML
|page_precedente=Tutoriel DTD
|page_parente=XML
|page_suivante=Tutoriel XSLT intermédiaire
|statut=à améliorer
|dernière_modif=2013/08/09
|page_prérequis=Tutoriel DTD
|voir_aussi=:en:XSLT Tutorial - Basics
|objectif=Comprendre l'utilité de XSLT, Savoir rédiger une simple feuille de style XSLT qui traduit un simple contenu XML vers (X)HTML uniquement avec des règles
|difficulté=débutant
|derniere_modif=false
|prérequis=XML
}}


==Objectifs==
<!-- <pageby nominor="false" comments="false"/> -->


* Avoir une idée de XSLT 1.0
== Introduction ==
* Savoir écrire des simples feuilles de transformations XML vers (X)HTML
<div class="tut_goals">
; Objectifs
* Comprendre l'utilité de XSLT
* Savoir rédiger une simple feuille de style XSLT qui traduit un simple contenu XML vers (X)HTML uniquement avec des règles (modèles/patrons)
; Prérequis
* [[Tutoriel DTD]]
; Suite
* [[Tutoriel XSLT intermédiaire]] (à améliorer)
; Niveau
* Débutant
; Remarques
* À étoffer un peu [...] et à vérifier. Ce tutoriel est utilisé dans le cours [[STIC:STIC I|STIC I]] et [[STIC:STIC II|STIC II]]
</div>


XSLT (''eXtensible Stylesheet Language Transformations'') est un langage de transformations d’arbres (fichiers) XML. XSLT est écrit en XML.


XSLT permet la génération d’autres contenus à partir d’un fichier XML, par exemple:
* du HTML (bien formé)
* du XML plus compliqué (tables de matières + règles de formatage XSL/FO)
* des extraits en XML ou HTML ...
* du SVG, X3D ou toutes sortes d’autres formats à partir de XML


==Notes:==
[[Image:xml-export-1.png|frame|none|Utilisation de XSLT]]


* Il reste pas mal d’améliorations à faire !!
'''Utilisation XSLT de base''':
* Limité à XSLT 1.0 (il existe déjà des processeurs pour XSLT 2.0)
* Il reste des lacunes ....


 
Il faut:
 
# Définir des règles qui disent comment transformer un "nœud" (élément, tag) et ses sous-éléments
=Table des matières détaillée=
 
 
 
=Introduction à XSLT=
 
 
 
====But de XSLT====
 
* XSLT est un langage de transformations d’arbres (fichiers) XML
* XSLT est écrit en XML
* XSLT permet la génération d’autres contenus à partir d’un fichier XML, par exemple:
** du HTML (bien formé)
** du XML plus compliqué (tables de matière + règles de formattage XSL/FO)
** des extraits en XML ou HTML ....
** du SVG, X3D ou toutes sortes d’autres formats à partir de XML
 
[[Image:xml-export-1.png]]
 
====Utilisation (mécanisme de base):====
 
# Définir des règles qui disent comment transformer un "noeud" (element, tag) et ses sous-éléments
# Organiser l’application de ces règles
# Organiser l’application de ces règles


 
'''Les feuilles de style XSLT'''
 
====Les feuilles de style XSLT====


* Une feuille de style XSLT est un document séparé qui contient des règles de transformation XSLT
* Une feuille de style XSLT est un document séparé qui contient des règles de transformation XSLT
* On peut associer une feuille de style XSL(T) à un (ou plusieurs) documents XML
* On peut associer une feuille de style XSL(T) à un (ou plusieurs) document XML
* Marche soit en "batch" (dans un éditeur ou en ligne de commande), soit avec un traitement "server-side", soit avec la plupart des clients Web modernes (Mozilla, IE6, etc.)
* Marche soit en "batch" (dans un éditeur ou en ligne de commande), soit avec un traitement "server-side", soit avec la plupart des clients Web modernes (Mozilla, IE6, etc.)


'''Documentation'''


* La spécification de XSLT 1.0 est formalisée (W3C Recommandation 16/11/99)
* http://www.w3.org/TR/xslt
* Voir aussi: [[:en:XSLT|XSLT]] (anglais)


====Documentation====
'''Compléments et alternatives à XSLT''':
 
* La spécification de XSLT 1.0 est formalisée (W3C Recommendation 16/11/99)
*  http://www.w3.org/TR/xslt
* A Tecfa: voir la page  [http://tecfa.unige.ch/guides/xml/xsl-pointers.html XML/XSL] dans la toolbox


XSLT repose sur un autre langage:
* XPath (langage pour indiquer un chemin dans un arbre):  http://www.w3.org/TR/xpath


XSLT est souvent utilisé pour produire des PDF:
* XSL/FO (mise en page):  http://www.w3.org/TR/xsl/


====Compléments à XSLT====
Alternative
 
* Xpath (langage pour indiquer un chemin dans un arbre):  http://www.w3.org/TR/xpath
* XSL/FO (mise en page):  http://www.w3.org/TR/xsl/
* XQuery (langage d’interrogation, bases de données XML): ,  http://www.w3.org/TR/xquery/
* XQuery (langage d’interrogation, bases de données XML): ,  http://www.w3.org/TR/xquery/


== Structure et utilisation d'un fichier XSLT==


Pour utiliser XSLT, deux fichiers sont nécessaires :
* Un fichier avec un contenu XML
* Un fichier XSLT
Il est possible d'associer le fichier XML dan le fichier XSLT pour que le navigateur fasse une traduction vers HTML. Donc ''dans ce cas'': un XML avec un XSLT associé va s'afficher comme HTML.


==Entêtes et utilisation des fichiers XSLT==
Exemple de sensibilisation:
* Affichez [http://tecfa.unige.ch/guides/xml/examples/dtd-examples/cuisine.xml cuisine.xml]
* Ensuite, regardez la source (CTRL-U dans Firefox)
* Ensuite, regardez la [http://tecfa.unige.ch/guides/xml/examples/dtd-examples/cuisine.xsl feuille de style]


=== Définition d’un fichier XSLT ===


XSLT est un langage [[XML]] et doit donc respecter le formalisme:
* Une déclaration XML pour commencer
* Une seule racine (''stylesheet'' pour XSLT)


===Définition d’un fichier XSLT===
<source lang="xml">
 
  <?xml version="1.0" ?>
  <?xml version="1.0" encoding="ISO-8859-1" ?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


  ....
  ....


  </xsl:stylesheet>
  </xsl:stylesheet>
</source>


* Normalement les fichiers XSLT ont l’extension *.xsl
Normalement les fichiers XSLT ont l’extension *.xsl
*  xmlns:xsl="URL" définit un "namespace" pour les balises XSL
* Donc dans nos exemples toutes les balises XSL commencent par  "xsl:"
* Le fait que toutes les balises XSL commencent par  xsl: empêche toute confusion


Il faut ensuite définir un namespace pour distinguer les balises XSL du langage cible. Dans l'exemple ci-dessus:
* '''xmlns:xsl="http://www.w3.org/1999/XSL/Transform''' définit le "namespace" pour les balises XSL
* '''version="1.0''' définit la version de XSLT


Dans nos exemples toutes les balises XSL commencent par  "xsl:". On aurait pu choisir un autre préfixe comme "xslt" ou encore "xs". Le nom du préfixe n'a '''jamais''' d'importance. On aurait aussi pu définir XSLT comme espace de nommage par défaut et préfixer nos balises XML plus les balises HTML à générer. Par contre, le nom de l'URL est défini par le standard et il faut l'utiliser tel quel. Notez qu'il existe déjà une version 2 (mais mal implémentée dans les navigateurs ...).


===Association d’un fichier XSLT à un fichier XML===
En résumé: copiez simplement le modèle ci-dessus.


=== Association d’un fichier XSLT à un fichier XML ===


 
Lorsqu'on utilise XSLT "client-side", c.à.d. dans un navigateur, il faut aussi dire au fichier XML où se trouve le XSLT avec l'instruction suivante:
====L’association peut se faire dans le fichier XML:====
<source lang="xml">
 
  <?xml version="1.0"?>
  <?xml version="1.0" encoding="ISO-8859-1"?>
  <?xml-stylesheet href="project.xsl" type="text/xsl"?>
  <?xml-stylesheet href="project.xsl" type="text/xsl"?>


Ligne 100 : Ligne 118 :


  </votre_xml>
  </votre_xml>
** Note: Il existe d’autres méthodes d’associations. Par exemple, dans un traitement "batch" on utilise une instruction comme  "saxon -o fichier.html fichier.xml fichier.xsl" pour dire "utilise tel fichier ".xsl" pour tel fichier ".xml" pour produire tel fichier ".html".
</source>
 
Note: Il existe d’autres méthodes pour utiliser un fichier XSLT avec un fichier XML. Par exemple, dans un traitement par lots ("batch processing"), on utilise une instruction comme  "saxon -o fichier.html fichier.xml fichier.xsl" pour dire "utilise tel fichier ".xsl" pour tel fichier ".xml" afin de produire tel fichier ".html". On peut également utiliser un processeur XSLT depuis un langage de scripting comme PHP.
 
 
==Principe de fonctionnement de XSLT==


* XSLT est un véritable langage de programmation
== Principe de fonctionnement de XSLT illustré avec des exemples ==


XSLT est un véritable langage de programmation implémentant deux paradigmes de programmation: La programmation par règles (introduite ici) et la programmation fonctionnelle.


=== Utilisation simple de XSLT ===


====Utilisation simple de XSLT====
La transformation du document source (XML) se fait selon des règles (facteurs conditionnels):
 
* Une feuille de style XSL contient un jeu de règles qui déclare comment traduire des éléments XML (selon leur contexte).
* La transformation du document source (XML) se fait selon des règles (facteurs conditionnels)
* Imaginez que l'on veuille traduire un commentaire défini par une balise XML <nowiki><commentaire></nowiki> en une construction HTML "<nowiki><dl></nowiki>" qui ajoute encore les mots "le commentaire" comme ci-dessous:
* Une feuille de style XSL contient un jeu de règles qui déclarent comment traduire des éléments XML (selon leur contexte).
* On peut imaginer qu’on veuille traduire un commentaire défini par une balise XML <commentaire> en une construction html " <dl> " comme ci-dessous:
 
L’expression XML suivante:


Donc on aimerait traduire le fragment XML suivant:
  <commentaire> xxxx </commentaire>
  <commentaire> xxxx </commentaire>
pourrait donner:
en HTML suivant:
 
<source lang="xml">
  <DL>
  <dl>
      <DT>Commentaire  </DT>
    <dt>Le commentaire:</dt>
      <DD> xxxx </DD>
    <dd> xxxx </dd>
  </DL>
</dl>
* Le but d’une feuille de style XML serait de définir une transformation pour chaque balise XML
</source>
 


Une feuille de style XML (simple) contiendra donc des règles pour transformer chaque balise XML en HTML.


====Une simple règle de traduction (appelée "template" en XSLT):====
'''Une simple règle de traduction (appelée "template" en XSLT):'''


[[Image:xml-export-2.png]]
[[Image:xml-export-2.png]]


''' Exemple de traduction d’une balise "commentaire" en "dl/dt/dl"'''
<source lang="xml">
<xsl:template match="commentaire">
<dl>
    <dt>Le commentaire:</dt>
    <dd><xsl:apply-templates/></dd>
</dl>
</xsl:template>
</source>


''' Exemple de traduction d’une balise "title" en "h1" centrée'''


===Traduction d’une balise "title" en "h1" centrée===
'''Source XML à traduire:'''
 
<source lang="xml">
 
 
====Source XML à traduire:====
 
  <title>Hello friend</title>
  <title>Hello friend</title>
</source>


 
'''La règle XSLT:'''
====La règle XSLT:====


[[Image:xml-export-3.png]]
[[Image:xml-export-3.png]]


==Un simple exemple XSLT==
=== Sensibilisation XML + XSLT avec un exemple ===


 
Voici quelques fichiers exemples que l'on va discuter et que vous pouvez télécharger (à sauver directement sans ouvrir (!) en utilisant "click-droit/sauver le lien sous", ou équivalent dans votre navigateur.
 
===Sensibilisation XML + XSLT===


*  http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.dtd (DTD)
*  http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.dtd (DTD)
Ligne 160 : Ligne 178 :
*  http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.html (résultat)
*  http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.html (résultat)


'''Le fichier XML (sans feuille de style):'''


 
Ce fichier contient un contenu XML très simple. La racine est l'élément ''page''.
====Le fichier XML (sans feuille de style):====
<source lang="xml">
 
  <?xml version="1.0"?>
  <?xml version="1.0"?>
  <page>
  <page>
Ligne 170 : Ligne 188 :
   <comment>Written by DKS/Tecfa, adapted from S.M./the Cocoon samples </comment>
   <comment>Written by DKS/Tecfa, adapted from S.M./the Cocoon samples </comment>
  </page>
  </page>
</source>


'''Le "document" XHTML résultant que l’on désire obtenir:'''


====Le "document" XHTML résultant que l’on désire obtenir:====
<source lang="xml">
 
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
  <html><head><title>Hello Cocoon friend</title></head><body bgcolor="#ffffff">
  <html>
  <h1 align="center">Hello Cocoon friend</h1>
<head><title>Hello Cocoon friend</title></head>
  <p align="center"> Here is some content :) </p>
  <body bgcolor="#ffffff">
  <hr> Written by DKS/Tecfa, adapted from S.M./the Cocoon samples
    <h1 align="center">Hello Cocoon friend</h1>
 
    <p align="center"> Here is some content :) </p>
    <hr> Written by DKS/Tecfa, adapted from S.M./the Cocoon samples
   </body></html>
   </body></html>
</source>


'''Le fichier XSL contiendra les règles de traduction'''
(c.f. plus loin pour les explications)


====Le fichier XSL:====
<source lang="xml">
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="page">
  <xsl:template match="page">
  <html>
    <head> <title> <xsl:value-of select="title"/>
              </title>
    </head>


.....
     <body bgcolor="#ffffff">
 
     <html> <head> <title> <xsl:value-of select="title"/>
</title> </head>
    <body bgcolor="#ffffff">
       <xsl:apply-templates/>
       <xsl:apply-templates/>
    </body>
  </html>
</xsl:template>


    </body>
<xsl:template match="title">
     </html>
     <h1 align="center"> <xsl:apply-templates/> </h1>
  </xsl:template>
</xsl:template>


   
  <xsl:template match="content">
  <p align="center"> <xsl:apply-templates/> </p>
</xsl:template>


  <xsl:template match="title">
<xsl:template match="comment">
 
   <hr /> <xsl:apply-templates/>
    <h1 align="center"> <xsl:apply-templates/>
</xsl:template>
  </h1>
</xsl:stylesheet>
   </xsl:template>
</source>
 
 
 
  <xsl:template match="content">
    <p align="center"> <xsl:apply-templates/> </p>
  </xsl:template>
 
 
  <xsl:template match="comment">
    <hr /> <xsl:apply-templates/>
  </xsl:template>
</xsl:stylesheet>
 
 
 
=XSL de base=
 
 
 
====Opérations de base:====


# Définir pour chaque balise une règle qui traduit la balise et son contenu
== XSL de base ==
# Organiser l’application de ces règles, c.a.d. indiquer comment traiter le contenu.
# Note: Rappelez-vous que XSL est du XML (donc il faut respecter les principes de validité et de bien formé (pas de balises croisés par exemple !)


'''Opérations de base:'''


# Définir pour chaque balise une règle qui traduit la balise et son contenu.
# Commencer par définir une règle qui gère la racine de votre XML. Cette règle doit produire la structure complète de la page HTML, c.à.d. produire les balises "HTML", "head" et "body".
# Organiser l’application de ces règles, c.à.d. indiquer comment traiter le contenu.
# Note: Rappelez-vous que XSL est du XML (donc il faut respecter les principes de validité et de bonne formation (pas de balises croisées par exemple !)).


====Rappel définition d’une règle ("template") avec xsl:template====
'''Rappel définition d’une règle ("template") avec xsl:template'''


[[Image:xml-export-4.png]]
[[Image:xml-export-4.png]]


===Exemples xsl:template match="xxx"===
=== Exemples xsl:template match="xxx" ===


Une règle applicable à toutes les balises "project":
Une règle applicable à toutes les balises "project":


<source lang="xml">
  <xsl:template match="project">
  <xsl:template match="project">
   ......
   ......


  </xsl:template>
  </xsl:template>
</source>


=== Anatomie d’une simple feuille de style ===


==Anatomie d’une simple feuille de style==
Observez surtout la règle pour l'élément racine qui est "page" !


[[Image:xml-export-5.png]]
[[Image:xml-export-5.png]]


==Application de templates aux sous-éléments==
===Application de templates aux sous-éléments===
 


Utilisation de '''xsl:apply-templates'''


===<xsl:apply-templates />===
Ici, on définit une simple règle qui se déclenchera en premier. Ceci dit, nous ne conseillons pas de définir une règle pour "/". Définissez seulement une règle pour l'élément racine. On montre cet exemple ici pour la simple raison qu'on le retrouve dans d'autres tutoriels. Le problème est que "/" ne correspond pas forcément à l'élément racine...
 
<source lang="xml">
* Ici on définit une simple règle pour la racine qui se déclenche (normalement) en premier):
 
   <xsl:template match="/">
   <xsl:template match="/">
     <html> <body>
     <html> <body>
Ligne 266 : Ligne 278 :
     </body> </html>
     </body> </html>
   </xsl:template>
   </xsl:template>
* Un simple apply-templates (sans attributs) examine tous les noeuds enfants dans l’ordre. Si une règle qui correspond à un noeud est détectée, elle sera appliquée
</source>
Un simple apply-templates (sans attribut) examine tous les nœuds enfants dans l’ordre. Si une règle qui correspond à un nœud est détectée, elle sera appliquée


<source lang="xml">
  <page>
  <page>
  <title>Hello Cocoon friend</title>
  <title>Hello Cocoon friend</title>
Ligne 273 : Ligne 287 :
   <comment>Written by DKS/Tecfa, adapted from S.M./the Cocoon samples </comment>
   <comment>Written by DKS/Tecfa, adapted from S.M./the Cocoon samples </comment>
  </page>
  </page>
</source>
* Pour le XML ci-dessus, les 2 règles pour "title" et "content" se déclencheraient!
* Pour le XML ci-dessus, les 2 règles pour "title" et "content" se déclencheraient!


<source lang="xml">
  <xsl:template match="title">
  <xsl:template match="title">
     <h1 align="center"> <xsl:apply-templates/> </h1>
     <h1 align="center"> <xsl:apply-templates/> </h1>
   </xsl:template>
   </xsl:template>
  <xsl:template match="content"
  <xsl:template match="content">
>
     <p align="center"> <xsl:apply-templates/> </p>
     <p align="center"> <xsl:apply-templates/> </p>
  </xsl:template>
  </xsl:template>
</source>


'''L’attribut "select" de apply-templates''':


===L’attribut "select" de apply-templates===
Il permet de spécifier que seule une règle pour un élément spécifique (défini par un XPath) est à appliquer (au lieu de toutes les règles applicables à tous les enfants). Autrement dit, on donne l’ordre explicite de chercher et d’appliquer toutes les règles à disposition pour un seul type d’élément identifié par un XPath. Dans l’exemple ci-dessous la règle déclenchée pour un élément <page> lance seulement la règle qui s’applique au sous-élément <title>
 
<source lang="xml">
* permet de spécifier un élément défini par un XPath (au lieu de tous les enfants),
* Autrement dit, on donne l’ordre explicite de chercher et d’appliquer toutes les règles à disposition pour un seul type d’élément identifé par un XPath
* Dans l’exemple ci-dessous la règle déclenchée pour un élément <page> lance seulement la règle qui s’applique au sous-élément <title>
  <xsl:template match="page">
  <xsl:template match="page">
   <xsl:apply-templates select
   <xsl:apply-templates select="title"/>
="title"/>
  </xsl:template>
  </xsl:template>
</source>
Cette règle pourrait s’appliquer au texte XML suivant:
Cette règle pourrait s’appliquer au texte XML suivant:


<source lang="xml">
  <page>
  <page>
   <title>Hello Cocoon friend</title>
   <title>Hello Cocoon friend</title>
   <content>
   <content>
   Here is some content. Olé !
   Here is some content. Olé !
   </content>
   </content>
   <comment>
   <comment>
      Written by DKS/Tecfa, adapted from S.M./the Cocoon samples
  Written by DKS/Tecfa, adapted from S.M./the Cocoon samples
 
   </comment>
   </comment>
  </page>
  </page>
*  http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.xml
</source>


Source: [http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.xml hello-page.xml]


=== Déroulement de l’exécution des règles ===


==Déroulement de l’exécution des règles==
En simplifiant .....


En simplifiant .....
(1) Le "moteur" XSLT cherche d’abord à exécuter la première règle qu’il trouve pour l’élément racine ou le cas échéant, pour le "début du fichier XML" ("/")


* Le "moteur" XSLT cherche d’abord à exécuter la  première règle qu’il trouve pour l’élément racine.
(2) Cette première règle doit faire appel à d’autres règles (sinon l'exécution va s'arrêter et les autres règles seront ignorées). Il existe deux alternatives pour "faire appel" à d'autres règles:
* Cette règle normalement fait appel à d’autres règles
* implicitement (solution préférable):  <xsl:apply-templates/>
** soit implicitement :  <xsl:apply-templates/>
* en faisant appel à des règles précises:  <xsl:apply-templates select="regle"/>
** soit en faisant appel à des règles précises:  <xsl:apply-templates select="regle"/>
* Chacune des sous-règles qui peuvent s’appliquer sera exécutée dans l’ordre et ainsi de suite
* Chacune des sous-règles qui peuvent s’appliquer sera exécutée dans l’ordre et ainsi de suite
* Le processeur ne trouve que les règles qui s’appliquent aux enfants du contexte actuel !!!
* Le processeur ne trouve que les règles qui s’appliquent aux enfants du contexte actuel !!! Voici un exemple qui ne marchera pas: [http://tecfa.unige.ch/guides/xml/examples/simple/hello-page-wrong.xml hello-page-wrong.xml] + [http://tecfa.unige.ch/guides/xml/examples/simple/hello-page-wrong-html.xsl hello-page-wrong-html.xsl]
[http://tecfa.unige.ch/guides/xml/examples/simple/hello-page-wrong.xml http://tecfa.unige.ch/guides/xml/examples/simple/hello-page-wrong.xml ]


<source lang="xml">
  <page>
  <page>
   <title>Hello Cocoon friend</title>
   <title>Hello Cocoon friend</title>
   <content
   <content> <p> Here is some content. Olé ! </p> </content>
> <p> Here is some content. Olé ! </p> </content
   <comment> Written by DKS/Tecfa, adapted from S.M./the Cocoon samples  
>
  </comment>
   <comment
> Written by DKS/Tecfa, adapted from S.M./the Cocoon samples </comment
>
  </page>
  </page>
La règle suivante ne marche pas, car comment n’est pas un enfant de content
</source>
 
La règle qui gère la racine est la suivante:
<source lang="xml">
<xsl:template match="page">
  <html>
    <head>
    <title>
      <xsl:value-of select="title"/>
    </title>
    </head>
    <body bgcolor="#ffffff">
      <xsl:apply-templates select="title"/>
      <xsl:apply-templates select="content"/>
    </body>
  </html>
  </xsl:template>
</source>
La règle suivante ne sera jamais trouvée par le processeur (ne marche pas), car ''comment'' n’est pas un enfant de ''content''
<source lang="xml">
  <xsl:template match="content">
  <xsl:template match="content">
   <xsl:apply-templates select
   <xsl:apply-templates select="comment"/>
="comment"/>
  </xsl:template>
  </xsl:template>
La règle suivante marche:
</source>
 
La règle suivante par contre marche:
<source lang="xml">
  <xsl:template match="content">
  <xsl:template match="content">
   <xsl:apply-templates select
   <xsl:apply-templates select="p"/>
="p>
  </xsl:template>
  </xsl:template>
 
</source>




Remarque: on ne doit pas se limiter à utiliser des règles "simples" correspondant uniquement à un nœud.
En fait la syntaxe qui régit les attributs ''match'' et ''select'' est une syntaxe XPath (présentée [[#XPATH et extraction de valeurs | ci-dessous]])
qui est beaucoup plus puissante.
Il est possible de sélectionner les nœuds selon leur contexte, leurs attributs et bien d'autres choses.


=XPATH et extraction de valeurs=
=== XPATH ===


* Pour mieux comprendre le fonctionnement des "templates" et pour aborder l’instruction  <xsl:value-of .... /> (qui permet d’extraire des informations d’un document source), <br /> il faut avoir des notions du langage "XPath"...
Pour mieux comprendre le fonctionnement des "templates" et pour aborder l’instruction  <nowiki><xsl:value-of .... /> </nowiki>(qui permet d’extraire des informations d’un document source), il faut avoir des notions du langage "[[Tutoriel XPath |XPath]]". XPath permet d’identifier un ou plusieurs fragments d’un document XML (cela rappelle les sélecteurs de CSS).
* XPath permet d’identifier un ou plusieurs fragments d’un document XML (cela rappelle les sélecteurs de CSS)


Pour une présentation détaillée, voir le [[Tutoriel XPath]].


'''Exemple d’un simple XPATH:'''


====Exemple d’un simple XPATH:====
<source lang="xml">
 
<xsl:template match="page">
<xsl:template match="page
   <xsl:apply-templates select="title"/>
">
   <xsl:apply-templates select
="title
"/>
  </xsl:template>
  </xsl:template>
"page" et "title sont des expressions XPath définissant un chemin de localisation
</source>


"
''"page"'' et ''"title"'' sont des expressions XPath définissant un '''chemin de localisation'''.


<source lang="xml">
  <xsl:template match="content">
  <xsl:template match="content">
   <xsl:apply-templates select
   <xsl:apply-templates select="page/comment"/>
="page/comment
"/>
</xsl:template>
</xsl:template>
"/page/comment" est une expression XPath un peu plus compliquée
</source>
 
XPath est nettement plus puissant que les sélecteurs CSS. Avec XPath vous pouvez par exemple dire "Identifiez le 4ème mot du 2ème paragraph qui suit un titre qui commence par le mot ’début’".
 
 


==Récapitulatif de chemins simples de localisations XPATH==
'''/page/comment''' est une expression XPath un peu plus compliquée


XPath est nettement plus puissant que les sélecteurs CSS. Avec XPath vous pouvez par exemple dire ''Identifiez le 4ème mot du 2ème paragraphe qui suit un titre commençant par le mot "début"''. Voici quelques expressions XPath un peu plus compliquées:


<source lang="xml">
//Etudiant[starts-with(Prenom,'Bernadette')]
//Participant[string-length(Nom)>=8]
author [(last() - 4) <= position()) and (position() <= last()
cours/module[position()=1]/section[position()=2]
</source>
XPath est utilisé par d'autres langages, par exemple XQuery et nous allons introduire plus de XPath dans un autre tutoriel... Voir aussi: [http://tecfa.unige.ch/guides/tie/html/xml-xpath/xml-path.html xml-xpath.html] (transparents)


====Voir aussi:====
==== Récapitulatif de chemins simples de localisation XPATH ====


*  [http://tecfa.unige.ch/guides/tie/html/xml-xpath/xml-path.html http://tecfa.unige.ch/guides/tie/html/xml-path/xml-xpath.html ]
Pour écrire des règles XSLT simples, il suffit de retenir que XPath fonctionne comme les chemins de fichier sur Unix ou dans les liens HTML.


{| border="1"
{| border="1"
! rowspan="1" colspan="1" |
! colspan="1" rowspan="1" | Elément syntaxique
Elément <br /> syntaxique
! colspan="1" rowspan="1" | (Type de chemin)
! rowspan="1" colspan="1" |
! colspan="1" rowspan="1" | Exemple d’un chemin
(Type de chemin)
! colspan="1" rowspan="1" | Exemple d’un match réussi par rapport au chemin indiqué à gauche
! rowspan="1" colspan="1" |
|-
Exemple d’un chemin
| colspan="1" rowspan="1" | balise
! rowspan="1" colspan="1" |
| colspan="1" rowspan="1" | nom d’élément
Exemple d’un match réussi par rapport au chemin indiqué à gauche
| colspan="1" rowspan="1" | project
| colspan="1" rowspan="1" | <nowiki> <project> ...... </project> </nowiki>
|-
| colspan="1" rowspan="1" | /
| colspan="1" rowspan="1" | sépare enfants directs
| colspan="1" rowspan="1" | project/title
| colspan="1" rowspan="1" | <nowiki><project> <title> ... </title></nowiki>
|-
| colspan="2" rowspan="1" |
| colspan="1" rowspan="1" |/
| colspan="1" rowspan="1" |(le "tout" du fichier XML, correspond souvent à l’élément racine)
|-
| colspan="1" rowspan="1" |//
| colspan="1" rowspan="1" |descendant
| colspan="1" rowspan="1" |project//title
| colspan="1" rowspan="1" |<nowiki><project><problem> <title>....</title></nowiki>
|-
| colspan="1" rowspan="1" |document('autre_doc.xml')
| colspan="1" rowspan="1" |à partir d'un autre document xml
| colspan="1" rowspan="1" |document('project.xml')/project
| colspan="1" rowspan="1" |<nowiki><project>....</project></nowiki> (du document xml externe)
|-
| colspan="2" rowspan="1" |
| colspan="1" rowspan="1" |//title
| colspan="1" rowspan="1" |<nowiki><racine>... <title>..</title> (n'importe où) </nowiki>
|-
|-
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" | <nowiki>*</nowiki>
balise
| colspan="1" rowspan="1" | "wildcard"
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" | <nowiki>*/title</nowiki>
nom d’élément
| colspan="1" rowspan="1" | <nowiki><bla> <title>..</title>  et  <bli> <title>...</title></nowiki>
| rowspan="1" colspan="1" |
project
| rowspan="1" colspan="1" |
<project> ...... </project>
|-
|-
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" | <nowiki>|</nowiki>
/
| colspan="1" rowspan="1" |opérateur "ou"
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |<nowiki>title|head</nowiki>
sépare enfants directs
| colspan="1" rowspan="1" |<nowiki><title>...</title>  ou <head> ...</head></nowiki>
| rowspan="1" colspan="1" |
project/title
| rowspan="1" colspan="1" |
<project> <title> ... </title>
|-
|-
| rowspan="1" colspan="2" |
| colspan="2" rowspan="1" |
 
| colspan="1" rowspan="1" |<nowiki>*|/|@*</nowiki>
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |(tous les éléments: les enfants, la racine et les attributs de la racine)
/
| rowspan="1" colspan="1" |
(correspond à l’élément racine)
|-
|-
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |.
//
| colspan="1" rowspan="1" |élément courant
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |.
descendant
| colspan="1" rowspan="1" |
| rowspan="1" colspan="1" |
project//title
| rowspan="1" colspan="1" |
<project><problem> <title>....</title>
|-
|-
| rowspan="1" colspan="2" |
| colspan="1" rowspan="1" |../
 
| colspan="1" rowspan="1" |élément supérieur
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |../problem
//title
| colspan="1" rowspan="1" |<nowiki><project></nowiki>
| rowspan="1" colspan="1" |
<racine>... <title>..</title> (n’mporte où)
|-
|-
| rowspan="1" colspan="1" |
| colspan="1" rowspan="4" |@
<nowiki>*</nowiki>| rowspan="1" colspan="1" |
| colspan="1" rowspan="4" |nom d’attribut
"wildcard"
| colspan="1" rowspan="1" |@id
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |<nowiki><xyz id="test">...</xyz></nowiki>
<nowiki>*/title</nowiki>| rowspan="1" colspan="1" |
<bla> <title>..</title>  et  <bli> <title>...</title>
|-
|-
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |project/@id
<nowiki>|</nowiki>| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |<nowiki><project id="test" ...> ... </project></nowiki>
opérateur "ou"
| rowspan="1" colspan="1" |
title|head
| rowspan="1" colspan="1" |
<title>...</title>  ou <head> ...</head>|-
| rowspan="1" colspan="2" |
 
| rowspan="1" colspan="1" |
<nowiki>*|/|@*</nowiki>| rowspan="1" colspan="1" |
(tous les éléments: les enfants, la racine et les attributs de la racine)
|-
|-
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |@attr=’type’
.
| colspan="1" rowspan="1" |Identife tous les attributs d'un type (identique à "@")
| rowspan="1" colspan="1" |
élément courant
| rowspan="1" colspan="1" |
.
| rowspan="1" colspan="1" |
 
|-
|-
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |list[@type=’ol’]
../
| colspan="1" rowspan="1" |<nowiki> <list type="ol"> ...... </list></nowiki>
| rowspan="1" colspan="1" |
élément supérieur
| rowspan="1" colspan="1" |
../problem
| rowspan="1" colspan="1" |
<project>|-
| rowspan="1" colspan="1" |
@
| rowspan="1" colspan="1" |
nom d’attribut
| rowspan="1" colspan="1" |
@id
| rowspan="1" colspan="1" |
<xyz id="test">...</xyz>|-
| rowspan="1" colspan="2" |
 
| rowspan="1" colspan="1" |
project/@id
| rowspan="1" colspan="1" |
<project id="test" ...> ... </project>
|-
|-
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |position()
@attr=’type’
| colspan="1" rowspan="1" |position de l'élément par rapport au parent
| rowspan="1" colspan="1" |
| colspan="1" rowspan="1" |position()
| colspan="1" rowspan="1" |


| rowspan="1" colspan="1" |
list[@type=’ol’]
| rowspan="1" colspan="1" |
<list type="ol"> ...... </list>
|-
|-
| rowspan="1" colspan="2" |
| colspan="1" rowspan="1" |last()
| colspan="1" rowspan="1" |nombre d'éléments dans un contexte
| colspan="1" rowspan="1" |last()
| colspan="1" rowspan="1" |position()!=last()
|}


| rowspan="1" colspan="1" |
=== Exemple (simple) d'utilisation de XPath pour contextualiser l'affichage ===


| rowspan="1" colspan="1" |
Grâce à XPath, il est notamment possible de sélectionner certains nœuds selon l'endroit où ils se trouvent dans la fichier XML.
Par exemple, imaginons le fichier XML suivant, qui décrit un étudiant rattaché à une faculté.


|}
<source lang="xml">
<etudiant>
  <nom>Dupond</nom>
  <prenom>Jean</nom>
  <faculte>
    <nom>FPSE</nom>
  </faculte>
</etudiant>
</source>


La balise ''nom'' apparaît deux fois dans des contextes différents et il est probable que l'on veuille l'afficher différemment.
Une solution possible serait de construire un code comme
<source lang="xml">
<xsl:template match="etudiant">
<p>
          <xsl:apply-template select="nom"/>
          <xsl:apply-templates select="prenom"/>
</p>
<p>
                <!-- une étape de traitement qui semble inutile pour afficher le nom de la faculté : -->
<xsl:apply-templates select="faculte" />
</p>
</xsl:template>


<!-- une ligne qui ne fait essentiellement rien : -->
<xsl:template match="faculte">
<xsl:apply-templates select="nom" />
</xsl:template>


==Extraction d’une valeur==
<!-- deux lignes pour essentiellement la même chose : -->
<xsl:template match="nom">
<xsl:value-of select="."/>
</xsl:template>


<xsl:template match="prenom">
<xsl:value-of select="."/>
</xsl:template>
</source>
qui est assez long et dont certaines lignes sont relativement pauvres.
Avec XPath, on peut récrire tout ca en beaucoup plus court et facile a lire :
<source lang="xml">
<xsl:template match="etudiant">
<p>
<xsl:apply-template select="nom"/>
<xsl:apply-templates select="prenom"/>
</p>
<p>
                <!-- on sélectionne directement le nom de la faculté -->
<xsl:apply-templates select="faculte/nom" />
</p>
</xsl:template>


<!-- on utilise "|" pour effectuer le même traitement aux nœuds "nom" et "prenom" -->
<xsl:template match="nom|prenom">
<xsl:value-of select="."/>
</xsl:template>
</source>


===xsl:value-of===
Dans cet exemple, on a utilisé le sélecteur "faculte/nom" pour sélectionner directement le nœud "nom" qui se trouve à l'intérieur de "faculte", sans avoir besoin de définir un template intermédiaire pour le nœud "faculte".
 
De plus, on utilise les opérateurs de XPath pour ne pas avoir à réécrire inutilement les mêmes instructions pour afficher le nom et le prénom.
* Sélectionne le résultat d’un XPath et le copie vers le document "sortie"
* Autrement dit: on extrait le contenu d’sous-élément, la valeur d’un attribut, etc.
 


== Extraction d’une valeur avec XSLT ==


====Exemple:====
=== Extraire la valeur (texte) d'un nœud ===
Les instructions '''xsl:value-of''' et '''{...}'''


* La règle suivante se déclenche dès qu’une balise <projet> est trouvée
''xsl:value-of'' sélectionne le résultat d’un XPath et le copie vers le document "sortie". Autrement dit: on peut extraire directement le contenu d’un sous-élément, la valeur d’un attribut, etc. Syntaxe:
<source lang="xml">
  <xsl:value-of select=" ..... "/>
</source>
'''Exemple:'''
* La règle suivante se déclenche dès qu’une balise <projet> est trouvée.
* Elle insère dans le document de sortie le contenu de l’élément <title> qui se trouve à l’intérieur d’un sous-élément <problem>
* Elle insère dans le document de sortie le contenu de l’élément <title> qui se trouve à l’intérieur d’un sous-élément <problem>
<source lang="xml">
  <xsl:template match="project">
  <xsl:template match="project">
     <P>
     <P>
Ligne 527 : Ligne 584 :
     </P>
     </P>
   </xsl:template>
   </xsl:template>
</source>


==== Générer un attribut ====


====Syntaxe spéciale pour insérer la valeur d’un objet dans le string d’un attribut à générer:====
===== syntaxe {...} =====
 
'''Attention''': il faut utiliser une autre syntaxe spéciale pour insérer la valeur d’un objet dans la chaîne de caractères d’un attribut à générer:
<source lang="xml">
  {....}
  {....}
 
</source>
<xsl:template match="contact-info">
<source lang="xml">
Voici un exemple
<xsl:template match="contact-info">
  ....
  ....
 
  <a href="mailto:{@email} ">
  <a href="mailto:{@email}
<xsl:value-of select="@email"/></a>
"><xsl:value-of select="@email"/></a>
  ...
  ...
</source>


{@email} insère la valeur de l’attribut email de l’élément courrant, par exemple:
Dans l'exemple la syntaxe <code>{@email}</code> insère la valeur de l’attribut email de l’élément courant à l'intérieur de '''l'attribut "href" généré''' alors que la syntaxe <code><xsl:value-of select="@email"/></code> insère la valeur de l'attribut email de l'élément courant à l'intérieur du '''texte de l'élément A généré'''.


Grâce à cette syntaxe <code>{@email}</code> on pourra générer par exemple:
  <contact-info email="test@test">
  <contact-info email="test@test">




===xsl:copy===
La même syntaxe s'utilise pour les cibles dans le document:
<source lang="xml">
<a href="#{test}"></a>
</source>
ou hors du document xml courant:
<source lang="xml">
href="document.xml#{text}"
</source>
et pour les ancres:
<source lang="xml">
<a name="{test}"/>
</source>
 
 
===== xsl:attribute =====
 
Une autre technique consiste à utiliser l'élément <xsl:attribute>, pour créer un nœud attribut dans l'élément de sortie ( en l'occurrence ici un élément html).
 
Dans l'exemple suivant, on indique que l'on veut créer un attribut dont le nom est "src" dans l'élément  <img> et on utilise <xsl:value-of> pour sélectionner la valeur à lui associer.
 
<source lang="xml">
Voici le même exemple
<xsl:template match="contact-info">
....
  <a>
  <xsl:attribute name="href">
      mailto:<xsl:value-of select="@email"/>
  </xsl:attribute>
  </a>
...
</source>
 
C'est une méthode très générale permettant d'introduire n'importe quel attribut dans un élément et par exemple de combiner la valeur de plusieurs nœuds pour cela.


* Sert à copier "tel quel" un élément source vers le document produit
Ci-dessous, il y a un autre exemple qui introduit un attribut src complexe pour des images hébergées sur un serveur distant. 
* Copie les balises et le contenu !
 
<source lang="xml">
Fichier XML :
<imagesDistantes>
  <serveur>mon.serveur.com</serveur>
  <image>image1.jpg</image>
  <image>image2.jpg</image>
</imagesDistantes>
</source>
 
<source lang="xml">
Fichier XSL qui reconstruit les URL des images :
<xsl:template match="image">
  <IMG>
    <xsl:attribute name="src">
      http://<xsl:value-of select="/imagesDistantes/serveur" />/<xsl:value-of select="."/>
    </xsl:attribute>
  </IMG>
</xsl:template>
</source>


Le code généré par le template "image" sera alors
<source lang="html4strict">
<IMG src="http://mon.serveur.com/image1.jpg"></IMG>
</source>


* Vous pouvez également créer ainsi plusieurs attributs :
Ci-dessous, il y a un autre exemple qui introduit un attribut "id" et "width" dans un div
pour spécifier son nom et sa largeur.
<source lang="xml">
<DIV>
  <xsl:attribute name="id">
    <xsl:value-of select="division/nom" />
  </xsl:attribute>
<xsl:attribute name="width">
    <xsl:value-of select="division/taille_image" />
  </xsl:attribute>
</DIV>
</source>


====Scénarios d’usage====
==== xsl:copy ====
L'instruction '''xsl:copy'''
* Sert à copier "tel quel" un élément source vers le document produit
* Copie les balises et le contenu !


* Utile pour reproduire l’original (ici un tag <p>...</p>)
'''Scénarios d’usage'''


* Utile pour reproduire l’original (ici un tag <nowiki><p>...</p></nowiki>)
<source lang="xml">
   <xsl:template match="p">
   <xsl:template match="p">
     <xsl:copy> <xsl:apply-templates/> </xsl:copy>
     <xsl:copy> <xsl:apply-templates/> </xsl:copy>
   </xsl:template>
   </xsl:template>
* Utile pour récupérer tout ce qui n’a pas été défini, mais attention si le tag ne correspond pas à un tag HTML il faut regarder le source HTML produit et agir ....
</source>


* Utile pour récupérer tous les éléments pour lesquels vous n'avez pas défini de règles. Mais attention: Si la balise recopiée ne correspond pas à un tag HTML, rien ne va s'afficher et il faut regarder la source de HTML produite et agir ....
<source lang="xml">
  <xsl:template match="*">
  <xsl:template match="*">
     <xsl:copy>Garbage: <i> <xsl:apply-templates/> </i> </xsl:copy>
     <xsl:copy>Garbage: <i> <xsl:apply-templates/> </i> </xsl:copy>
   </xsl:template>
   </xsl:template>
* Le fragment suivant copie tous les éléments non traités par les autres templates:
</source>
** utile si vous utilisez des balises XHTML que vous ne désirez pas traiter ou encore si XSLT sert juste à "enrichir" votre code XML (genre table de matières)
Le fragment suivant copie tous les éléments ''et'' attributs non traités par les autres templates. C'est une technique utile si vous utilisez beaucoup de balises XHTML dans votre XML et que vous ne désirez pas traiter (par flemme) ou encore si XSLT sert juste à "enrichir" votre code XML (genre table de matières)
 
<source lang="xml">
  <xsl:template match="*|@*">
  <xsl:template match="*|@*">
   <xsl:copy>
   <xsl:copy>
Ligne 573 : Ligne 712 :
   </xsl:copy>
   </xsl:copy>
   </xsl:template>
   </xsl:template>
</source>


'''A éviter:''' Il vaut mieux contrôler et écrire une règle explicite pour tout élément qui peut se trouver dans votre XML !


=Exemples=
== Exemples et cas particuliers ==
 
 
 
==Utilisation de apply-templates et XPath==
 
* Avant d’utiliser des constructions avancées comme "if" ou "for-each", réfléchissez bien si c’est vraiment nécessaire. Dans la plupart des cas il suffit de définir des règles avec "xsl:apply-templates" et le reste "s’organise" tout seul.
 


Voici quelques exemples commentés.


===Simple XML vers HTML avec XSLT===
===Simple XML vers HTML avec XSLT===


* http://tecfa.unige.ch/guides/xml/examples/xsl-simple/ (fouiller le répertoire !)
Code:
* http://tecfa.unige.ch/guides/xml/examples/xsl-simple/simple-xpath-apply.xml
* http://tecfa.unige.ch/guides/xml/examples/xsl-simple/simple-xpath-apply.xsl


*  http://tecfa.unige.ch/guides/xml/examples/xsl-simple/ (le répertoire !)


 
Un texte en XML:
===Un texte en XML===
<source lang="xml">
 
  <arbre>
  <arbre>
   <para>Simples Templates et XPath</para>
   <para>Simples Templates et XPath</para>
Ligne 606 : Ligne 743 :
   </uncle>
   </uncle>
  </arbre>
  </arbre>
</source>


La feuille de style XSLT:


===La feuille de style XSLT===
Ici on veut produire un simple HTML à partir du XML, avec les consignes suivantes:
 
* On aimerait que les enfants de <aunt> et <uncle> soient affichés différemment
* Ici on veut produire un simple HTML à partir du XML, avec les consignes suivantes:
* Le premier enfant de <uncle> doit être affiché spécialement aussi
** On aimerait que les enfants de <aunt> et <uncle> soient affichés différemment
* Si voulez savoir comment ce code s’exécute, consultez le fichier [http://tecfa.unige.ch/guides/xml/examples/xsl-simple/simple-xpath-apply-trace.xml ...-trace.xml]
** Le prermier enfant de <uncle> doit être affiché spécialement aussi
* Si voulez savoir comment ce code s’exécute, consultez le fichier *-trace.xml


<source lang="xml">
   <xsl:template match="arbre">
   <xsl:template match="arbre">
   <html><title>XSL Example</title><body>
   <html><title>XSL Example</title><body>
Ligne 620 : Ligne 758 :
     </body> </html>
     </body> </html>
   </xsl:template>
   </xsl:template>
   


   <xsl:template match="uncle|aunt">
   <xsl:template match="uncle|aunt">
     <hr /> <xsl:apply-templates />
     <hr /> <xsl:apply-templates />
   </xsl:template>
   </xsl:template>
   


   <xsl:template match="name">
   <xsl:template match="name">
   <xsl:apply-templates /> :
   <xsl:apply-templates /> :
   </xsl:template>
   </xsl:template>
   


   <xsl:template match="uncle/child[position()=1]">
   <xsl:template match="uncle/child[position()=1]">
Ligne 642 : Ligne 776 :
   <p style="color:blue"><xsl:apply-templates /></p>
   <p style="color:blue"><xsl:apply-templates /></p>
   </xsl:template>
   </xsl:template>
</source>


 
Le résultat en HTML:
===Le résultat en HTML===
<source lang="xml">
 
  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  <!DOCTYPE html
 
  PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  <html>
  <html>
     <title>XSL Example</title>
     <title>XSL Example</title>
     <body>
     <body>
       Simples Templates et XPath
       Simples Templates et XPath
       <hr>
       <hr>
       Auntie :
       Auntie :
       <p style="color:blue">Je suis un enfant de aunt</p>
       <p style="color:blue">Je suis un enfant de aunt</p>
       <hr>
       <hr>
       Uncle Ben :
       Uncle Ben :
       <p><strong>Je suis le premier enfant de uncle</strong></p>
       <p><strong>Je suis le premier enfant de uncle</strong></p>
       <p>Je suis le 2eme enfant de uncle</p>
       <p>Je suis le 2eme enfant de uncle</p>
Ligne 666 : Ligne 795 :
     </body>
     </body>
  </html>
  </html>
</source>


=== Gestion de liens ===


==Gestion de liens==
Le formalisme XML en soi ne comprend pas les liens ! Il existe un langage XLink que vous pouvez utiliser (et qui fait partie des standards SVG). Sinon, vous inventez un élément ou encore un attribut pour ce type d’information et vous traduisez en <nowiki><a href ...> ... </a></nowiki>.
 
Le formalisme XML en soi ne comprend pas les liens !!
 
* Il existe un langage XLink que vous pouvez utiliser (et qui fait partie des standards SVG)
* Sinon, vous inventez un élément ou encore un attribut pour ce type d’information et vous traduisez en <a href ...>
 
 
===Traduction vers <a href="...">...</a>===


Traduction vers
<a href="...">...</a>:
C.f. le code source de ces fichiers !
*  http://tecfa.unige.ch/guides/xml/examples/xsl-links-to-url/links.xml
*  http://tecfa.unige.ch/guides/xml/examples/xsl-links-to-url/links.xml
*  http://tecfa.unige.ch/guides/xml/examples/xsl-links-to-url/links.xsl
*  http://tecfa.unige.ch/guides/xml/examples/xsl-links-to-url/links.xsl


c.f. le code source de ces fichiers !
Extraits du fichier XML:
 
 
 
===Extraits du fichier XML===
 
* On peut inventer une balise comme "url" pour l’URL et une autre balise comme "name" pour indiquer le nom du lien.
* On peut inventer une balise comme "url" pour l’URL et une autre balise comme "name" pour indiquer le nom du lien.


<source lang="xml">
   <address>
   <address>
     <name>TECFA</name>
     <name>TECFA</name>
     <url>http://tecfa.unige.ch</url>
     <url>http://tecfa.unige.ch</url>
   </address>
   </address>
 


   <address2>
   <address2>
Ligne 699 : Ligne 820 :
     <url>http://tecfa.unige.ch</url>
     <url>http://tecfa.unige.ch</url>
   </address2>
   </address2>
* Alternativement, on aurait pu mettre des informations dans un attribut
</source>


Alternativement, on aurait pu mettre des informations dans un attribut:
<source lang="xml">
   <address4 url="http://tecfa.unige.ch">TECFA</address4>
   <address4 url="http://tecfa.unige.ch">TECFA</address4>
   <address5 url="http://tecfa.unige.ch">TECFA</address5>
   <address5 url="http://tecfa.unige.ch">TECFA</address5>
</source>


 
Extraits du fichier XSLT:
===Extraits du fichier XSLT===


Pour address et address2 on crée des règles
Pour address et address2 on crée des règles
 
<source lang="xml">
  <xsl:template match="address">
  <xsl:template match="address">
   <a href="{url}
   <a href="{url}"> <xsl:value-of select="name "/> </a>
"> <xsl:value-of select="name
"/> </a>
  </xsl:template>
  </xsl:template>
 


  <xsl:template match="address2">
  <xsl:template match="address2">
     <xsl:apply-templates select="url"/>
     <xsl:apply-templates select="url"/>
  </xsl:template>
  </xsl:template>


  <xsl:template match="url">
  <xsl:template match="url">
   <a href="{.}"> <xsl:value-of select="../name"/> </a>
   <a href="{.}"> <xsl:value-of select="../name"/> </a>
  </xsl:template>
  </xsl:template>
</source>
address3 et address2 sont traitées directement depuis l’élément mère
address3 et address2 sont traitées directement depuis l’élément mère
 
<source lang="xml">
  <a href="{address3/url}"><xsl:value-of select="address3/name"/></a>
  <a href="{address3/url}"><xsl:value-of select="address3/name"/></a>
  <a href="{address4/@url}"><xsl:value-of select="address4"/></a>
  <a href="{address4/@url}"><xsl:value-of select="address4"/></a>
 
  <xsl:template match="address5">
  <xsl:template match="address5">
   <a href="{@url}"> <xsl:value-of select="."/> </a>
   <a href="{@url}"> <xsl:value-of select="."/> </a>
  </xsl:template>
  </xsl:template>
</source>
 
 
 
==Images==
 
* Il y n’a aucune magie spéciale pour gérer les images !
* Simplement:
** Examinez votre XML
** Trouvez un moyen pour traduire en HTML (ou autre chose)
 


=== Images ===


===Insertion d’images===
Il y n’a aucune magie spéciale pour gérer les images ! Simplement:
 
* Examinez votre XML
 
* Trouvez un moyen pour traduire en HTML (ou autre chose)
 
Insertion d’images:
====Fichier XML====


'''Fichier XML''':
<source lang="xml">
  <?xml version="1.0"?>
  <?xml version="1.0"?>
  <?xml-stylesheet href="images.xsl" type="text/xsl"?>
  <?xml-stylesheet href="images.xsl" type="text/xsl"?>
Ligne 757 : Ligne 868 :
   <title>Hello Here are my images</title>
   <title>Hello Here are my images</title>
   <list>
   <list>
     <image>
     <image>dolores_001.jpg</image>
dolores_001.jpg</image>
 
     <image>dolores_002.jpg</image>
     <image>dolores_002.jpg</image>
     <image>dolores_002.jpg</image>
     <image>dolores_002.jpg</image>
     <image2>scrolls.jpg </image2>
     <image2>scrolls.jpg </image2>
     <image2>scrolls.jpg </image2>
     <image2>scrolls.jpg </image2>
     <image3
     <image3 source="dolores_002.jpg">Recipe image</image3>
  source="dolores_002.jpg">Recipe image</image3>
 
   </list>
   </list>
   <comment>Written by DKS.</comment>
   <comment>Written by DKS.</comment>
  </page>
  </page>
 
</source>


'''XSLT stylesheet''':
* Une règle pour la balise "list"


<source lang="xml">
<xsl:template match="list">
  Apply templates for "image" elements:
  <!-- lancer la règle -->
  <xsl:apply-templates select="image"/>
  <!-- Va insérer le premier élément "image2" trouvé -->
  <p> <img src="{image2}"/> </p>
  <!-- Gérer l'élément image3 (avec un attribut) -->
    <xsl:apply-templates select="image3"/>
</xsl:template>
</source>


====XSLT stylesheet====
Une règle pour la balise "image" (c.f. ci-dessus )
<source lang="xml">
<xsl:template match="image">
  <p> <img src="{.}"/> </p>
</xsl:template>
</source>


* Une règle pour la balise "list"
Une règle pour la balise "image3"
<source lang="xml">
<xsl:template match="image3">
  <p> <img src="{@source}"/>
      <xsl:value-of select="."/>
  </p>
</xsl:template>
</source>
Voyez, il existe pleins de solutions ! Donc on répète: XSLT ne connaît ni HTML ni les images ni quoi que ce soit. C'est '''vous''' qui définissez comment un XML va se traduire en HTML !


<xsl:template match="list">
== Gestion d'un nœud selon le contexte : l'attribut "mode" ==
    Apply templates for "image" elements:


    <xsl:apply-templates select="image
Souvent il est souhaitable de pouvoir définir plusieurs comportements différents pour le même nœud :
"/>
* quand le type de nœud est utilisé à différents endroits du même document XML ;
 
* quand le même nœud doit être affiché plusieurs fois dans le document généré.


    This will only insert the first "image2" element contents it finds:
=== Nœud utilisé à des endroits différents du XML ===
Il y a de nombreux cas où le nœud est utilisé à des endroits différents du fichier XML
(par exemple un nœud ''nom'' qui serait utilisé pour le nom d'une personne, à afficher en rouge,
et pour le nom de sa faculté, à afficher en noir).
Dans ces cas, il est souvent préférable de régler le problème avec différents sélecteurs XPath et des templates intermédiaires.
Pour cela voir les sections [[Tutoriel XSLT débutant#Application de templates aux sous-éléments|Application de templates aux sous-éléments]], [[Tutoriel XSLT débutant#XPATH|XPATH]] et [[Tutoriel XSLT débutant#Exemples et cas particuliers|Exemples et cas particuliers]].


    <p> <img src="{image2}"/> </p>
=== Nœud utilisé plusieurs fois dans le fichier XSL ===
 


    And another template for a tag image3 element (with an attribute)
Pour cela, il est souvent nécessaire de modifier radicalement le traitement du nœud. Cela est particulièrement utile lorsque le nœud est complexe (c'est-à-dire composé de plusieurs sous-éléments).


    <xsl:apply-templates select="image3
L'attribut ''mode'' fonctionne ici comme un sélecteur qui permet de définir plusieurs templates concernant le même nœud (c'est-à-dire avec le même attribut ''match'').
"/>
</xsl:template>
* Une règle pour la balise "image"


  <xsl:template match="image">
Par exemple, si l'on imagine un fichier XML qui présente un livre avec le titre et l'image de couverture (éléments ''<titre>'' et ''<couverture>''). On souhaitera sûrement pouvoir afficher une vignette avec la couverture en petit ainsi qu'une version en grand format. On pourrait utiliser un code comme
    <p> <img src="{.}
<source lang="xml">
"/> </p>
<!-- image en petit -->
  </xsl:template>
<img width="100px><xsl:apply-templates select="couverture"/></img>
* Une règle pour la balise "image3"
<!-- image en grand -->
<img width="500px><xsl:apply-templates select="couverture"/></img>


  <xsl:template match="image3">
<xsl:template match="couverture">
    <p> <img src="{@source}
  <xsl:attribute name="src"><xsl:value-of select="."/></xsl:attribute>
"/><xsl:value-of select="."/>
</xsl:template>
  </p>
</source>
  </xsl:template>


Mais cela aurait pour conséquence de séparer le tab ''img'' en deux endroits du XSL, ce qui peut devenir problématique en cas de modification ultérieure du document.


==Fabrication de références (liens)==
La solution alternative avec ''mode'' permet de faciliter les modifications ultérieures :
<source lang="xml">
<!-- l'image en petit -->
<xsl:apply-template select="couverture" mode="petit" />
<!-- l'image en grand -->
<xsl:apply-template select="couverture" mode="grand" />


<xsl:template match="couverture" mode="petit">
    <img width="100px" src="{.}"/>
</xsl:template>


<xsl:template match="couverture" mode="grand">
    <img width="500px" src="{.}"/>
</xsl:template>
</source>


===Table de matières pour éléments qui ont un identificateur===
=== Exemple d'utilisation : fabrication de références (liens) ===


[http://tecfa.unige.ch/guides/xml/examples/recit/ http://tecfa.unige.ch/guides/xml/examples/recit/]
Table des matières pour éléments qui ont un identificateur:
* On utilise ici un attribut "mode" dans la définition des templates et apply-templates
*  http://tecfa.unige.ch/guides/xml/examples/recit/
* Cela nous permet d’écrire plusieurs règles pour un même noeud
On utilise ici un attribut "mode" dans la définition des templates et apply-templates
* Cela nous permet d’écrire plusieurs règles pour un même nœud
* Ici par exemple, on utilise mode="toc" pour fabriquer une table des matières
* Ici par exemple, on utilise mode="toc" pour fabriquer une table des matières


'''Fragment XSLT (fait d’abord la table des matières, ensuite le reste)'''


 
<source lang="xml">
====Fragment XSLT (fait d’abord la table des matières, ensuite le reste)====
 
  <xsl:template match="/">
  <xsl:template match="/">
   <html>
   <html>
Ligne 837 : Ligne 983 :
   </html>
   </html>
  </xsl:template>
  </xsl:template>
</source>


'''Fragments XSLT pour gérer la balise "EPISODE": 2 règles dont une avec un mode'''
<source lang="xml">


====Fragments XSLT pour gérér la balise "EPISODE": 2 règles dont une avec un mode====
  <xsl:template match="EPISODE" mode="toc">
 
   <a href="#{@id}"> <xsl:value-of select="SousBut"/> </a> -
  <xsl:template match="EPISODE" mode="toc"
>
   <a href="#{@id}">
<xsl:value-of select="SousBut"/></a> -
 
  </xsl:template>
  </xsl:template>
  <xsl:template match="/RECIT/FIL/EPISODE">
   
   <a name="{@id}"
<xsl:template match="/RECIT/FIL/EPISODE">
> <hr /> </a>
   <a name="{@id}"> <hr /> </a>
   <xsl:apply-templates/>
   <xsl:apply-templates/>
  </xsl:template>
  </xsl:template>
</source>


===Tables des matières pour éléments sans ID===


===Tables de matières pour éléments sans ID===
Plus difficile car il faut "fabriquer" des attributs "name" et "href" pour le HTML
 
* la solution adoptée ici est moche et à refaire (on aurait pu compter les éléments)
* plus difficile car il faut "fabriquer" des attributs "name" et "href" pour le HTML
** la solution adopté ici est moche (on aurait pu compter les éléments)
* il s’agit des jours d’un atelier webmaster qu’on peut consulter ici:
* il s’agit des jours d’un atelier webmaster qu’on peut consulter ici:
*  http://tecfa.unige.ch/tecfa/teaching/formcont/webmaster2003/programme/
*  http://tecfa.unige.ch/tecfa/teaching/formcont/webmaster2003/programme/
Ligne 865 : Ligne 1 009 :
** matos.xsl, resume.xsl, animateurs.xsl créent des extraits variés du programme.
** matos.xsl, resume.xsl, animateurs.xsl créent des extraits variés du programme.


 
'''Fragments XSLT'''
 
<source lang="xml">
====Fragments XSLT====
 
 
 
  <!-- Code qui fabrique la table des matières (jours) en HTML -->
  <!-- Code qui fabrique la table des matières (jours) en HTML -->
  Programme: <xsl:apply-templates select="//day" mode="toc"
  Programme: <xsl:apply-templates select="//day" mode="toc"/>
  />
 


  <xsl:template match="day" mode="toc">
  <xsl:template match="day" mode="toc">
Ligne 883 : Ligne 1 021 :
  <!-- Code pour insérer des attributs "name" dans le HTML -->
  <!-- Code pour insérer des attributs "name" dans le HTML -->
  <xsl:template match="day">
  <xsl:template match="day">
     <a name="{@name}{@dayno}{@month}"
     <a name="{@name}{@dayno}{@month}" >
><xsl:value-of select="@name"/></a> -         <xsl:value-of select="@dayno"/>/<xsl:value-of select="@month"/>/
    <xsl:value-of select="@name"/></a> -  
 
    <xsl:value-of select="@dayno"/>/<xsl:value-of select="@month"/>/
     <xsl:value-of select="@year"/>
     <xsl:value-of select="@year"/>
  </xsl:template>
  </xsl:template>
 
</source>
 
 


====Fragment XML (élément à extraire)====
'''Fragment XML (élément à extraire)'''


* Faire une table des matières avec les jours de l’Atelier (avec liens)
Faire une table des matières avec les jours de l’Atelier (avec liens)


  <day name="lundi" year="2003" month="6" dayno="16">
  <day name="lundi" year="2003" month="6" dayno="16">


'''Résultat HTML'''


====Résultat HTML====
Au début du fichier on a un menu qui affiche les jours (liens vers le bas)
 
* Au début du fichier on a un menu qui affiche les jours (liens vers le bas)


  Programme: <a href="#lundi166">lundi</a> - <a href="#mardi176">mardi</a> - ....
  Programme: <a href="#lundi166">lundi</a> - <a href="#mardi176">mardi</a> - ....
  ......
  ......


Ligne 911 : Ligne 1 045 :
  <a name="lundi166">lundi</a> - 16/6/2003
  <a name="lundi166">lundi</a> - 16/6/2003


'''Note:''' Dans ce répertoire il y a aussi un fichier programme-fo.xsl qui génère du code xsl-fo utilisé pour générer la version PDF du programme.
===Tables des matières pour éléments sans ID===
* Table des matières pour une "page travaux STAF" (portfolio étudiant)
* On liste les travaux
*  http://tecfa.unige.ch/guides/xml/examples/xsl-toc/
== Variables et templates avec paramètres ==


Il possible en XSLT de définir des variables ('''attention''' il s'agit en fait de constantes, car '''leur valeur n'est pas modifiable''') ainsi que de faire passer des paramètres aux templates.
Cela permet un traitement modulable des nodes.


====Note:====
=== xsl:variable ===
La syntaxe d'une "variable" en XSLT est


* Dans ce répertoire il y a aussi un fichier programme-fo.xsl qui génère du code xsl-fo utilisé pour générer la version PDF du programme.
  <xsl:variable name="nom" select="expression"> Contenu </xsl:variable>


* Si l'attribut ''select'' est présent, alors le contenu ''Contenu'' doit être vide.
* l'attribut ''select'' peut faire référence à un nœud, dans ce cas la variable prendra la valeur du contenu du nœud ;
* l'attribut ''select'' peut faire référence à un attribut (référencé par ''@nom_attribut''), dans ce cas la variable prendra la valeur du contenu de l'attribut;
* l'attribut ''select'' peut faire référence à une chaîne de caractères (entre guillemets simples), dans ce cas la variable prendra la valeur de la chaîne ;
* l'attribut ''select'' peut faire même référence à une autre variable (référencée par ''$nom_variable''), dans ce cas la variable prendra la valeur de la variable indiquée ;
* Si le nœud, l'attribut ou la variable indiquée n'existe pas, la variable prendra la valeur d'une chaîne de caractères vide (''""'').


''' Souvenez-vous, il n'est pas possible de modifier la valeur d'une variable après son attribution ! '''


===Tables de matières pour éléments sans ID===


* Table des matières pour une "page travaux STAF" (portfolio étudiant)
'''Référence à une variable'''
* On liste les travaux
Pour faire référence à une variable il suffit de faire précéder son nom par ''$''.
*  http://tecfa.unige.ch/guides/xml/examples/xsl-toc/
 
Une variable appelée ''url'' peut être définie par


  XML : <url>www.google.com</url>


  XSL: <xsl:variable name="url" select="url"/>
  ou  <xsl:variable name="url"><xsl:value-of select="url"/></xsl:variable>


=Déclarations et style=
et peut être utilisée par exemple par
<source lang="xml">
  <a href="http://{$url}">$url</a>
</source>


Pour une autre utilisation des variables, voir le [[Tutoriel_pour_générer_du_SVG_avec_du_XSLT#Visualisation_de_nombres | Tutoriel XSLT pour générer du SVG]].


=== xsl:param et xsl:with-param ===


==Déclaration de la sortie==
On peut également utiliser des paramètres dans les template.


* Veillez à ce que le fichier produit corresponde aux normes, c.à.d qu’il contienne les déclarations nécessaires pour chaque type de document.
''' déclaration d'un paramètre dans un template : xsl:param '''
Cela fonctionne comme les variables à l'exception du fait que les valeurs peuvent être définies lors de l'appel du template (donc modifiées par le template appelant).


Pour définir un paramètre dans un template on utilise le code


  <xsl:param name="nom" select="valeur par défaut" />


===xsl:output===
La valeur par défaut n'est pas obligatoire. Dans le cas où elle est omise en revanche on sera contraint d'appeler le template en spécifiant toujours une valeur pour le paramètre.


permet de définir le type de sortie qui sera produit et de générer des entêtes. Voici la syntaxe (simplifiée) pour XSL V 1.0 (1999)
'''attribution d'une valeur au paramètre : xsl:with-param'''
Lors de l'appel par un autre template, il faut spécifier la valeur du paramètre (sauf si on veut utiliser la valeur par défaut) comme suit :


<xsl:output<br /> method = "xml" | "html" | "text"<br /> version = nmtoken<br /> encoding = string<br /> omit-xml-declaration = "yes" | "no"<br /> standalone = "yes" | "no"<br />doctype-public = string<br /> doctype-system = string<br /> indent = "yes" | "no"<br />media-type = string />
  <xsl:apply-templates select="un_selecteur_XPath">
* A mettre au début du fichier (après xsl:stylesheet)
    <xsl:with-param name="nom_paramètre" select="valeur_du_paramètre" />
* Ci-dessous qqs. exemples
  </xsl:appy-templates>


Par exemple, lors d'un environnement multilingue, on peut avoir un fichier XML comme suit


<source lang="xml">
<doc>
<titre>
  <en>The Title</en>
  <fr>Le Titre</fr>
</titre>
</doc>
</source>


===Output en HTML 4.01 transitionnel===
Pour n'afficher que les informations en français (nœud ''fr'') on utilise donc
<source lang="xml">
<xsl:apply-templates select="titre">
    <!-- on sélectionne la langue française -->
    <xsl:with-param name="lang" select="'fr'" />
</xsl:apply-templates>


  <xsl:output method="html"     encoding="ISO-8859-1"     doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
  <xsl:template match="titre">
 
  <!-- langue affichée : par défaut l'anglais -->
  <xsl:param name="lang" select="en" />
  <xsl:value-of select="$lang" />
</xsl:template>
</source>


== Déclarations et style ==


Veillez à ce que le fichier produit corresponde aux normes, c.à.d. qu’il contienne les déclarations nécessaires pour chaque type de document.


===Output en XHTML "façon light"===
===xsl:output===


<xsl:output
permet de définir le type de sortie qui sera produit et de générer des entêtes. Voici la syntaxe (simplifiée) pour XSL V 1.0 (1999):


    method="html"
<source lang="xml">
<xsl:output>
method = "xml" | "html" | "text"
version = nmtoken
encoding = string
omit-xml-declaration = "yes" | "no"
standalone = "yes" | "no"
doctype-public = string
doctype-system = string
indent = "yes" | "no"
media-type = string
/>
</source>


    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
* A mettre au début du fichier (après xsl:stylesheet)
* Ci-dessous quelques exemples


    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
===Output en HTML 4.01 transitionnel===


    indent="yes"
<source lang="xml">
<xsl:output method="html"
      doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
</source>


    encoding="iso-8859-1"
===Output en XHTML "façon light"===


<source lang="xml">
<xsl:output
    method="html"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    indent="yes"
  />
  />
 
</source>


===Output en XHTML "pur" (page XML) et transitionnel===
===Output en XHTML "pur" (page XML) et transitionnel===


<source lang="xml">
  <xsl:stylesheet version="1.0"
  <xsl:stylesheet version="1.0"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns="http://www.w3.org/1999/xhtml">
                 xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output
  <xsl:output
     method="xml"
     method="xml"
     doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
     doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
     doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
     doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
     indent="yes"
     indent="yes"
    encoding="iso-8859-1"
  />
  />
 
</source>


===Output en XHTML "pur" et strict===
===Output en XHTML "pur" et strict===


<source lang="xml">
  <xsl:stylesheet version="1.0"
  <xsl:stylesheet version="1.0"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns="http://www.w3.org/1999/xhtml">
                 xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output
  <xsl:output
     method="xml"
     method="xml"
     doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
     doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
     doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
     doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
     indent="yes"
     indent="yes"
    encoding="UTF-8"
/>
</source>


    encoding="iso-8859-1"
===Output en SVG===


<source lang="xml">
<xsl:output
  method="xml"
  indent="yes"
  standalone="no"
  doctype-public="-//W3C//DTD SVG 1.0//EN"
  doctype-system="http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd"
  media-type="image/svg"
  />
  />
</source>
=== Output en HTML5 ===
HTML5 est plus délicat, puisque la spécification XSLT a été créée avant HTML5. Comme HTML5 n'est ni SGML ni XML, il n'existe pas de solution élégante .....
; Example - Output en HTML 5


<source lang="xml">
<xsl:output
    method="html"
    doctype-system="about:legacy-compat"
    encoding="UTF-8"
    indent="yes" />


===Output en SVG===
<xsl:template match="/">
  <html>
    <head>
      <meta charset="utf-8"/>
      <title>HTML5 + SVG example</title>
    </head>
    <body>
.....
        </body>
</html>
</source>


<xsl:output
On peut aussi produire du XML, mais ensuite enlever l'entête XML ....
<source lang="xml">
<xsl:output
    method="xml"
    omit-xml-declaration = "yes"
    encoding="UTF-8"
    indent="yes" />


  method="xml"
<xsl:template match="/">


  indent="yes"
  <html>
  <xsl:text disable-output-escaping="yes">
<![CDATA[<!DOCTYPE html>]]>
  </xsl:text>
    <head>
      <meta charset="utf-8"/>
      <title>HTML5 + SVG example</title>
    </head>
    <body>
.....
        </body>
</html>
</source>


  standalone="no"
; Example - sérialisation en XHTML5


  doctype-public="-//W3C//DTD SVG 1.0//EN"
Voici la meilleure solution:
<source lang="xml">
<xsl:output
    method="xml"
    omit-xml-declaration = "yes"
    doctype-system="about:legacy-compat"
    encoding="UTF-8"
    indent="yes" />
</source>


  doctype-system="http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd"
ou encore:
<source lang="xml">
<xsl:output
    method="xml"
    doctype-system="about:legacy-compat"
    encoding="UTF-8"
    indent="yes" />
</source>


  media-type="image/svg"
Autre méthode (ne marche pas dans Firefox 19)


/>
<source lang="xml">
<xsl:output
    method="xml"
    encoding="UTF-8"
    indent="yes" />


<xsl:template match="/">
  <xsl:text disable-output-escaping="yes">
<![CDATA[<!DOCTYPE html>]]>
  </xsl:text>
  <html xmlns="http://www.w3.org/1999/xhtml">
    <head>...</head>
    <body>.....</body>
    </html>
</source>


===Output en VRML===
===Output en VRML===


<source lang="xml">
  <xsl:output method="text"
  <xsl:output method="text"
   encoding="UTF-8"
   encoding="UTF-8"
   media-type="model/vrml"/>
   media-type="model/vrml"/>
  ....
  ....
Ligne 1 046 : Ligne 1 320 :


  ......
  ......
</source>


== CSS pour le résultat de la transformation ==


Lorsque vous produisez du HTML ou du XHTML, évitez de produire du HTML "vieille école" (balises "font", etc.). Il est simple d’associer une feuille de style CSS ! Vous "faites" comme à la main. Donc il faut insérer la balise "link" à l’endroit ou le <head> est généré.


==CSS pour le résultat de la transformation==
<source lang="xml">
 
* Lorsque vous produisez du HTML ou du XHTML, évitez de produire du HTML "vieille école" (balises "font", etc.)
* Il est simple d’associer une feuille de style CSS ! Vous "faites" comme à la main. Donc il faut insérer la balise "link" à l’endroit ou le <head> est généré.
 
<xsl:template match="racine">
<xsl:template match="racine">
<html>
<html>
Ligne 1 064 : Ligne 1 337 :
</title>
</title>
</head>
</head>
 
</source>


==Générer plusieurs fichiers HTML à partir d’un seul XML==
==Générer plusieurs fichiers HTML à partir d’un seul XML==


* Marche uniquement lorsqu’on traite le fichier XML en "batch"
Marche uniquement lorsqu’on traite le fichier XML en "batch"
 
 


===Programme de l’Atelier WebMaster 2004===
===Programme de l’Atelier WebMaster 2004===
Ligne 1 077 : Ligne 1 348 :
*  [http://tecfa.unige.ch/tecfa/teaching/formcont/webmaster2004/programme/programme.xsl programme.xsl] (montre comment faire)
*  [http://tecfa.unige.ch/tecfa/teaching/formcont/webmaster2004/programme/programme.xsl programme.xsl] (montre comment faire)


<source lang="xml">
  <!-- au début du fichier -->
  <!-- au début du fichier -->
  <xsl:output name="daypage" method="html" encoding="ISO-8859-1"      doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
  <xsl:output name="daypage" method="html"      doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
  .....
  .....


Ligne 1 101 : Ligne 1 373 :


   </xsl:template>
   </xsl:template>
</source>
Quelques astuces:
Quelques astuces:


* Si vous devez générer plusieurs pages pour un élément du même nom, il faut générer des noms de fichiers uniques:
Si vous devez générer plusieurs pages pour un élément du même nom, il faut générer des noms de fichiers uniques:


<source lang="xml">
  <xsl:template match="day">
  <xsl:template match="day">
   <xsl:result-document href="{@name}{@dayno}{@month}.html" format="daypage">
   <xsl:result-document href="{@name}{@dayno}{@month}.html" format="daypage">
** dans l’exemple présent, on désire avoir une page / jour du programme. Chaque jour se distingue par une date spéciale (attributs dayno et month)
</source>
* Pour faire une table de matière (que vous pouvez inclure partout):
Dans l’exemple présent, on désire avoir une page / jour du programme. Chaque jour se distingue par une date spéciale (attributs dayno et month)
** Voici la règle qui génère la table:


Pour faire une table des matières (que vous pouvez inclure partout):
* Voici la règle qui génère la table:
<source lang="xml">
  <xsl:template match="day" mode="toc">
  <xsl:template match="day" mode="toc">
   <a href="{@name}{@dayno}{@month}.html"><xsl:value-of select="@name"/></a> -
   <a href="{@name}{@dayno}{@month}.html"><xsl:value-of select="@name"/></a> -


  </xsl:template>
  </xsl:template>
** Voici comment l’inclure:
</source>
 
<b>Programme</b>: <a href="programme.html"> Top</a> - <xsl:apply-templates select="//day" mode="toc"/>
 
 
=XSLT en "batch" et debugage=
 


Voici comment l’inclure:


====Avec un fichier de commande====
<b>Programme</b>: <a href="programme.html"> Top</a> - <xsl:apply-templates select="//day" mode="toc"/>


* Il existe plusieurs processeurs XSLT populaires qu’on peut utiliser pour produire un fichier de sortie à partir d’un xml + xslt. On conseille Saxon (ci-dessous)
== XSLT en "batch" et debugage ==
* Il faut passer par un processeur XSLT pour "debuger" une feuille de style XSLT client-side
** "View source" dans un navigateur ne montre pas le HTML !
** Donc maîtriser une "procédure manuelle" est intéressant !!
** Alternativement, il existe des outils de debugage pour certains éditeurs
* Certains outils nécessitent l’installation d’un environnement Java.
** il faut installer un runtime ou dévelopment kit Java pour utiliser les processeurs Xalan ou Saxon.
** Un engin Runtime ("JRE") suffit:
** Versions JRE 5 ou mieux !
*  http://java.sun.com/products/


Il faut apprendre à utiliser XSLT en "batch" pour plusieurs raisons. La plus importante est de pouvoir valider le HTML produit. Enfin, il existe aussi des extensions pour les navigateurs FireFox et IE qui permettent de voir le code HTML généré.


'''Avec un fichier de commande'''


====Avec un éditeur XML====
Il existe plusieurs processeurs XSLT populaires qu’on peut utiliser pour produire un fichier de sortie à partir d’un xml + xslt. On conseille Saxon (ci-dessous)
* Il faut passer par un processeur XSLT pour "déboguer" une feuille de style XSLT client-side
* "View source" dans un navigateur ne montre pas le HTML !
* Donc maîtriser une "procédure manuelle" est intéressant !!
* Alternativement, il existe des outils de débogage pour certains éditeurs.


* La plupart des éditeurs XML ont un processeur XSLT intégré (les versions commerciales ont des fonctions de debugage).
Certains outils nécessitent l’installation d’un environnement Java.
* il faut installer un runtime ou un Java development Kit pour utiliser les processeurs Xalan ou Saxon.
* Un engin Runtime ("JRE") suffit, à télécharger (si nécessaire) depuis http://java.sun.com/products/


'''Avec un éditeur XML''' (solution conseillée pour les débutants)


La plupart des éditeurs XML ont un processeur XSLT intégré (les versions commerciales ont des fonctions de débogage).


=Server-side avec PHP=
Dans XML Exchanger light, utilisez le menu Transform pour produire un HTML que vous pouvez ensuite valider.
* Ouvrir le fichier XML ou le tab si c'est déjà fait (pas XSLT !)
* Menu Transform
* Execute Advanced XSLT
** Cliquer sur "current" dans Input"
** Cliquer sur Use Processing Instructions dans XSL
** Output to New Document (ou File)


Ensuite, '''validez''' votre HTML


== XSLT avec PHP 5 ==


===XSLT avec PHP 5===
Le support XSLT est standard dans PHP 5. L’exemple ci-dessous applique une feuille de style travaux.xsl au fichier travaux.xml
 
** Le support XSLT est standard dans PHP 5
** L’exemple ci-dessous applique une feuille de style travaux.xsl au fichier travaux.xml
*  http://tecfa.unige.ch/guides/php/examples/xslt/php-xslt.php
*  http://tecfa.unige.ch/guides/php/examples/xslt/php-xslt.php
*  [http://tecfa.unige.ch/guides/php/examples/xslt/php-xslt.php http://tecfa.unige.ch/guides/php/examples/xslt/php-xslt.phps]
*  [http://tecfa.unige.ch/guides/php/examples/xslt/php-xslt.php http://tecfa.unige.ch/guides/php/examples/xslt/php-xslt.phps]
*  http://tecfa.unige.ch/guides/php/examples/xslt/php-xslt.text
*  http://tecfa.unige.ch/guides/php/examples/xslt/php-xslt.text


 
<source lang="PHP">
 
  $xml_file = ’travaux.xml’;
  $xml_file = ’travaux.xml’;
  $xsl_file = ’travaux.xsl’;
  $xsl_file = ’travaux.xsl’;


  // load the xml file (and test first if it exists)
  // load the xml file (and test first if it exists)
  $dom_object = new DomDocument();
  $dom_object = new DomDocument();
  if (!file_exists($xml_file)) exit(’Failed to open $xml_file’);
  if (!file_exists($xml_file)) exit(’Failed to open $xml_file’);
  $dom_object->load($xml_file);
  $dom_object->load($xml_file);
  // create dom object for the XSL stylesheet and configure the transformer
  // create dom object for the XSL stylesheet and configure the transformer
  $xsl_obj = new DomDocument();
  $xsl_obj = new DomDocument();
  if (!file_exists($xsl_file)) exit(’Failed to open $xsl_file’);
  if (!file_exists($xsl_file)) exit(’Failed to open $xsl_file’);
  $xsl_obj->load($xsl_file);
  $xsl_obj->load($xsl_file);
  $proc = new XSLTProcessor;
  $proc = new XSLTProcessor;
  $proc->importStyleSheet($xsl_obj); // attach the xsl rules
  $proc->importStyleSheet($xsl_obj); // attach the xsl rules
  $html_fragment = $proc->transformToXML($dom_object);
  $html_fragment = $proc->transformToXML($dom_object);
  print ($html_fragment);
  print ($html_fragment);
</source>


* Donc pour utiliser ce "service", il suffit de copier le fichier php-xslt.php et changer les 2 noms de fichiers (travaux.xml et travaux.xsl) au début <br /> (enfin depuis le web il faut prendre php-xslt.text et le renommer en xxx.php)
Donc pour utiliser ce "service", il suffit de copier le fichier php-xslt.php et changer les 2 noms de fichiers (travaux.xml et travaux.xsl) au début <br /> (enfin depuis le web il faut prendre php-xslt.text et le renommer en xxx.php)
 
 
 
=Client-side XML+XSLT avec Firefox 1.0+ ou IE6+=
 
* XSLT fonctionne sans problème avec les navigateurs IE, Mozilla/Firefox et Opera.


== Client-side XML+XSLT avec Firefox 1.0+ ou IE6+ ==


XSLT fonctionne sans problème avec les navigateurs IE, Mozilla/Firefox et Opera. Par contre, certains navigateurs comme Chrome refusent d'exécuter une page XML en local. Il faut la déposer sur un serveur.


===Un simple exemple===
===Un simple exemple===
Ligne 1 204 : Ligne 1 467 :
*  http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.xml (XML)
*  http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.xml (XML)
*  http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.html (résultat)
*  http://tecfa.unige.ch/guides/xml/examples/simple/hello-page.html (résultat)
* Il faut ajouter au moins la déclaration suivante (méthode de sérialisation)
 
Pour assurer que la sortie soit accepté comme HTML, il faut ajouter au moins la déclaration suivante (méthode de sérialisation), mais on conseille de faire une déclaration complète, déposer les fichiers sur un serveur et de tester la solution avec tous les navigateurs.


  <xsl:output method="html"/>
  <xsl:output method="html"/>
* Voir les fichiers pour les détails. Si aucun contenu n’est affiché ou s’il est mal affiché, faites "Menu->View->Source"
* Voir les fichiers pour les détails. Si aucun contenu n’est affiché ou s’il est mal affiché, faites "Menu->View->Source"
* Notes:
**  http://www.mozilla.org/releases/ (Mozilla downloads)
** Evitez de travailler avec IE 5.5. La version "normale" n’est pas conforme au standard XSLT. Installez soit IE 6.x ou 7.x soit MSXML3+,pour IE 5.5.
** Il faut s’assurer que le serveur Web indique le bon mime type pour xml et xsl (text/xml). Ceci est fait à Tecfa, mais pas forcément chez votre fournisseur....


Note: Il faut s’assurer que le serveur Web indique le bon mime type pour xml et xsl (text/xml). Ceci est fait à Tecfa, mais pas forcément chez votre fournisseur....


=Executive summary=
== Executive summary ==


# Create a XSLT stylesheet file: xxx.xsl
(1) Créer une feuille XSLT xxx.xsl
# Copy/paste the XSLT header and root element below (decide encoding as you like)
 
<?xml version="1.0" encoding="ISO-8859-1" ?>


(2) Copier/coller le code ci-dessous:
<source lang="xml">
<?xml version="1.0" ?>
  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
'
 


  </xsl:stylesheet>
  </xsl:stylesheet>
</source>


# Write a rule that deals with your XML root element
(3) Écrire une règle qui gère la racine. Cette règle doit produire l'entête, racine, head et body du HTML.
#* This rule must produce the root, head and body of the HTML (copy/paste this too)
<source lang="xml">
 
  <xsl:template match="page">
  <xsl:template match="page">
   <html>
   <html>
   <head> <title> <xsl:value-of select="title"/>  
   <head> <title> <xsl:value-of select="title"/>  
Ligne 1 240 : Ligne 1 495 :
   <body bgcolor="#ffffff">
   <body bgcolor="#ffffff">
       <xsl:apply-templates/>
       <xsl:apply-templates/>
   </body>
   </body>
   </html>
   </html>
  </xsl:template>
  </xsl:template>
</source>


# Write rules for  each (!!) of your XML elements,
(3) Écrire une règle pour chaque élément XML
#* for each insert some HTML, sometimes some text, or sometimes nothing
* Pour chaque règle il faut insérer (produire) soit du HTML, soit du texte, souvent les deux et finalement parfois rien du tout.
#* make sure to place a <xsl:apply-templates> inside each rule (usually between some HTML) ... unless you wish to censor contents.
* Il faut un <nowiki><xsl:apply-templates></nowiki> (ou équivalent) dans chaque règle, sauf si vous désirez censurer le contenu
# Associate this stylesheet with your XML file using:
#*  <?xml-stylesheet href="xxx.xsl" type="text/xsl"?>
 
 
 


(4) Associer cette feuille de style avec un fichier XML
<source lang="xml">
  <?xml-stylesheet href="xxx.xsl" type="text/xsl"?>
</source>


== Liens ==
== Liens ==


;
* [[XML]]
* [[Tutoriel XPath]]
* [[Tutoriel XSLT pour générer du SVG]] (Présente certaines fonctions avancées, comme les variables en XSL)
* [[XSLT Paramètres et variables]]


; Transparents
*  http://tecfa.unige.ch/guides/tie/html/xml-xslt/xml-xslt.html
*  http://tecfa.unige.ch/guides/tie/html/xml-xslt/xml-xslt.html
*  http://tecfa.unige.ch/guides/tie/pdf/files/xml-xslt.pdf
*  http://tecfa.unige.ch/guides/tie/pdf/files/xml-xslt.pdf


; Anglais
* [[:en:XSLT|XSLT]] (liens)
* [[:en:XSLT|XSLT Tutorial - Basics]]
* [http://en.wikipedia.org/wiki/XSLT_elements XSLT Elements list] (liste des éléments XSLT sur wikipedia)


[[Category: XML]]
[[Category: XML]]
[[Category: Ressources STIC]]
[[en:XSLT Tutorial - Basics]]
[http://www.w3schools.com/xsl/xsl_w3celementref.asp XSL reference card] liste des éléments XSLT

Dernière version du 23 mai 2021 à 19:45

XML
◀▬▬▶
à améliorer débutant
2021/05/23 ⚒⚒ 2013/08/09
Objectifs
  • Comprendre l'utilité de XSLT
  • Savoir rédiger une simple feuille de style XSLT qui traduit un simple contenu XML vers (X)HTML uniquement avec des règles
Voir aussi


Introduction

Objectifs
  • Comprendre l'utilité de XSLT
  • Savoir rédiger une simple feuille de style XSLT qui traduit un simple contenu XML vers (X)HTML uniquement avec des règles (modèles/patrons)
Prérequis
Suite
Niveau
  • Débutant
Remarques
  • À étoffer un peu [...] et à vérifier. Ce tutoriel est utilisé dans le cours STIC I et STIC II

XSLT (eXtensible Stylesheet Language Transformations) est un langage de transformations d’arbres (fichiers) XML. XSLT est écrit en XML.

XSLT permet la génération d’autres contenus à partir d’un fichier XML, par exemple:

  • du HTML (bien formé)
  • du XML plus compliqué (tables de matières + règles de formatage XSL/FO)
  • des extraits en XML ou HTML ...
  • du SVG, X3D ou toutes sortes d’autres formats à partir de XML
Utilisation de XSLT

Utilisation XSLT de base:

Il faut:

  1. Définir des règles qui disent comment transformer un "nœud" (élément, tag) et ses sous-éléments
  2. Organiser l’application de ces règles

Les feuilles de style XSLT

  • Une feuille de style XSLT est un document séparé qui contient des règles de transformation XSLT
  • On peut associer une feuille de style XSL(T) à un (ou plusieurs) document XML
  • Marche soit en "batch" (dans un éditeur ou en ligne de commande), soit avec un traitement "server-side", soit avec la plupart des clients Web modernes (Mozilla, IE6, etc.)

Documentation

Compléments et alternatives à XSLT:

XSLT repose sur un autre langage:

XSLT est souvent utilisé pour produire des PDF:

Alternative

Structure et utilisation d'un fichier XSLT

Pour utiliser XSLT, deux fichiers sont nécessaires :

  • Un fichier avec un contenu XML
  • Un fichier XSLT

Il est possible d'associer le fichier XML dan le fichier XSLT pour que le navigateur fasse une traduction vers HTML. Donc dans ce cas: un XML avec un XSLT associé va s'afficher comme HTML.

Exemple de sensibilisation:

Définition d’un fichier XSLT

XSLT est un langage XML et doit donc respecter le formalisme:

  • Une déclaration XML pour commencer
  • Une seule racine (stylesheet pour XSLT)
 <?xml version="1.0" ?>
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 ....

 </xsl:stylesheet>

Normalement les fichiers XSLT ont l’extension *.xsl

Il faut ensuite définir un namespace pour distinguer les balises XSL du langage cible. Dans l'exemple ci-dessus:

Dans nos exemples toutes les balises XSL commencent par "xsl:". On aurait pu choisir un autre préfixe comme "xslt" ou encore "xs". Le nom du préfixe n'a jamais d'importance. On aurait aussi pu définir XSLT comme espace de nommage par défaut et préfixer nos balises XML plus les balises HTML à générer. Par contre, le nom de l'URL est défini par le standard et il faut l'utiliser tel quel. Notez qu'il existe déjà une version 2 (mais mal implémentée dans les navigateurs ...).

En résumé: copiez simplement le modèle ci-dessus.

Association d’un fichier XSLT à un fichier XML

Lorsqu'on utilise XSLT "client-side", c.à.d. dans un navigateur, il faut aussi dire au fichier XML où se trouve le XSLT avec l'instruction suivante:

 <?xml version="1.0"?>
 <?xml-stylesheet href="project.xsl" type="text/xsl"?>

 <votre_xml>
 ......

 </votre_xml>

Note: Il existe d’autres méthodes pour utiliser un fichier XSLT avec un fichier XML. Par exemple, dans un traitement par lots ("batch processing"), on utilise une instruction comme "saxon -o fichier.html fichier.xml fichier.xsl" pour dire "utilise tel fichier ".xsl" pour tel fichier ".xml" afin de produire tel fichier ".html". On peut également utiliser un processeur XSLT depuis un langage de scripting comme PHP.

Principe de fonctionnement de XSLT illustré avec des exemples

XSLT est un véritable langage de programmation implémentant deux paradigmes de programmation: La programmation par règles (introduite ici) et la programmation fonctionnelle.

Utilisation simple de XSLT

La transformation du document source (XML) se fait selon des règles (facteurs conditionnels):

  • Une feuille de style XSL contient un jeu de règles qui déclare comment traduire des éléments XML (selon leur contexte).
  • Imaginez que l'on veuille traduire un commentaire défini par une balise XML <commentaire> en une construction HTML "<dl>" qui ajoute encore les mots "le commentaire" comme ci-dessous:

Donc on aimerait traduire le fragment XML suivant:

<commentaire> xxxx </commentaire>

en HTML suivant:

 <dl>
     <dt>Le commentaire:</dt>
     <dd> xxxx </dd>
 </dl>

Une feuille de style XML (simple) contiendra donc des règles pour transformer chaque balise XML en HTML.

Une simple règle de traduction (appelée "template" en XSLT):

Xml-export-2.png

Exemple de traduction d’une balise "commentaire" en "dl/dt/dl"

<xsl:template match="commentaire">
 <dl>
     <dt>Le commentaire:</dt>
     <dd><xsl:apply-templates/></dd>
 </dl>
</xsl:template>

Exemple de traduction d’une balise "title" en "h1" centrée

Source XML à traduire:

 <title>Hello friend</title>

La règle XSLT:

Xml-export-3.png

Sensibilisation XML + XSLT avec un exemple

Voici quelques fichiers exemples que l'on va discuter et que vous pouvez télécharger (à sauver directement sans ouvrir (!) en utilisant "click-droit/sauver le lien sous", ou équivalent dans votre navigateur.

Le fichier XML (sans feuille de style):

Ce fichier contient un contenu XML très simple. La racine est l'élément page.

 <?xml version="1.0"?>
 <page>
  <title>Hello Cocoon friend</title>
  <content>Here is some content :)  </content>
  <comment>Written by DKS/Tecfa, adapted from S.M./the Cocoon samples </comment>
 </page>

Le "document" XHTML résultant que l’on désire obtenir:

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
 <html>
 <head><title>Hello Cocoon friend</title></head>
  <body bgcolor="#ffffff">
     <h1 align="center">Hello Cocoon friend</h1>
     <p align="center"> Here is some content :) </p>
     <hr> Written by DKS/Tecfa, adapted from S.M./the Cocoon samples
   </body></html>

Le fichier XSL contiendra les règles de traduction (c.f. plus loin pour les explications)

 <?xml version="1.0"?>
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="page">
   <html> 
    <head> <title> <xsl:value-of select="title"/> 
               </title> 
    </head>

    <body bgcolor="#ffffff">
      <xsl:apply-templates/>
    </body>
   </html>
</xsl:template>

 <xsl:template match="title">
    <h1 align="center"> <xsl:apply-templates/> </h1>
 </xsl:template>

 <xsl:template match="content">
   <p align="center"> <xsl:apply-templates/> </p>
 </xsl:template>

 <xsl:template match="comment">
   <hr /> <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

XSL de base

Opérations de base:

  1. Définir pour chaque balise une règle qui traduit la balise et son contenu.
  2. Commencer par définir une règle qui gère la racine de votre XML. Cette règle doit produire la structure complète de la page HTML, c.à.d. produire les balises "HTML", "head" et "body".
  3. Organiser l’application de ces règles, c.à.d. indiquer comment traiter le contenu.
  4. Note: Rappelez-vous que XSL est du XML (donc il faut respecter les principes de validité et de bonne formation (pas de balises croisées par exemple !)).

Rappel définition d’une règle ("template") avec xsl:template

Xml-export-4.png

Exemples xsl:template match="xxx"

Une règle applicable à toutes les balises "project":

 <xsl:template match="project">
   ......

 </xsl:template>

Anatomie d’une simple feuille de style

Observez surtout la règle pour l'élément racine qui est "page" !

Xml-export-5.png

Application de templates aux sous-éléments

Utilisation de xsl:apply-templates

Ici, on définit une simple règle qui se déclenchera en premier. Ceci dit, nous ne conseillons pas de définir une règle pour "/". Définissez seulement une règle pour l'élément racine. On montre cet exemple ici pour la simple raison qu'on le retrouve dans d'autres tutoriels. Le problème est que "/" ne correspond pas forcément à l'élément racine...

  <xsl:template match="/">
     <html> <body>
       <xsl:apply-templates/>

     </body> </html>
   </xsl:template>

Un simple apply-templates (sans attribut) examine tous les nœuds enfants dans l’ordre. Si une règle qui correspond à un nœud est détectée, elle sera appliquée

 <page>
 <title>Hello Cocoon friend</title>
  <content>Here is some content :)  </content>
  <comment>Written by DKS/Tecfa, adapted from S.M./the Cocoon samples </comment>
 </page>
  • Pour le XML ci-dessus, les 2 règles pour "title" et "content" se déclencheraient!
 <xsl:template match="title">
    <h1 align="center"> <xsl:apply-templates/> </h1>
   </xsl:template>
 <xsl:template match="content">
    <p align="center"> <xsl:apply-templates/> </p>
 </xsl:template>

L’attribut "select" de apply-templates:

Il permet de spécifier que seule une règle pour un élément spécifique (défini par un XPath) est à appliquer (au lieu de toutes les règles applicables à tous les enfants). Autrement dit, on donne l’ordre explicite de chercher et d’appliquer toutes les règles à disposition pour un seul type d’élément identifié par un XPath. Dans l’exemple ci-dessous la règle déclenchée pour un élément <page> lance seulement la règle qui s’applique au sous-élément <title>

 <xsl:template match="page">
   <xsl:apply-templates select="title"/>
 </xsl:template>

Cette règle pourrait s’appliquer au texte XML suivant:

 <page>
  <title>Hello Cocoon friend</title>
  <content>
   Here is some content. Olé !
  </content>
  <comment>
   Written by DKS/Tecfa, adapted from S.M./the Cocoon samples
  </comment>
 </page>

Source: hello-page.xml

Déroulement de l’exécution des règles

En simplifiant .....

(1) Le "moteur" XSLT cherche d’abord à exécuter la première règle qu’il trouve pour l’élément racine ou le cas échéant, pour le "début du fichier XML" ("/")

(2) Cette première règle doit faire appel à d’autres règles (sinon l'exécution va s'arrêter et les autres règles seront ignorées). Il existe deux alternatives pour "faire appel" à d'autres règles:

  • implicitement (solution préférable): <xsl:apply-templates/>
  • en faisant appel à des règles précises: <xsl:apply-templates select="regle"/>
  • Chacune des sous-règles qui peuvent s’appliquer sera exécutée dans l’ordre et ainsi de suite
  • Le processeur ne trouve que les règles qui s’appliquent aux enfants du contexte actuel !!! Voici un exemple qui ne marchera pas: hello-page-wrong.xml + hello-page-wrong-html.xsl
 <page>
  <title>Hello Cocoon friend</title>
  <content> <p> Here is some content. Olé ! </p> </content>
  <comment> Written by DKS/Tecfa, adapted from S.M./the Cocoon samples 
  </comment>
 </page>

La règle qui gère la racine est la suivante:

<xsl:template match="page">
   <html>
    <head>
     <title>
      <xsl:value-of select="title"/>
     </title>
    </head>
    <body bgcolor="#ffffff">
      <xsl:apply-templates select="title"/>
      <xsl:apply-templates select="content"/>
    </body>
   </html>
  </xsl:template>

La règle suivante ne sera jamais trouvée par le processeur (ne marche pas), car comment n’est pas un enfant de content

 <xsl:template match="content">
   <xsl:apply-templates select="comment"/>
 </xsl:template>

La règle suivante par contre marche:

 <xsl:template match="content">
   <xsl:apply-templates select="p"/>
 </xsl:template>


Remarque: on ne doit pas se limiter à utiliser des règles "simples" correspondant uniquement à un nœud. En fait la syntaxe qui régit les attributs match et select est une syntaxe XPath (présentée ci-dessous) qui est beaucoup plus puissante. Il est possible de sélectionner les nœuds selon leur contexte, leurs attributs et bien d'autres choses.

XPATH

Pour mieux comprendre le fonctionnement des "templates" et pour aborder l’instruction <xsl:value-of .... /> (qui permet d’extraire des informations d’un document source), il faut avoir des notions du langage "XPath". XPath permet d’identifier un ou plusieurs fragments d’un document XML (cela rappelle les sélecteurs de CSS).

Pour une présentation détaillée, voir le Tutoriel XPath.

Exemple d’un simple XPATH:

<xsl:template match="page">
   <xsl:apply-templates select="title"/>
 </xsl:template>

"page" et "title" sont des expressions XPath définissant un chemin de localisation.

 <xsl:template match="content">
   <xsl:apply-templates select="page/comment"/>
</xsl:template>

/page/comment est une expression XPath un peu plus compliquée

XPath est nettement plus puissant que les sélecteurs CSS. Avec XPath vous pouvez par exemple dire Identifiez le 4ème mot du 2ème paragraphe qui suit un titre commençant par le mot "début". Voici quelques expressions XPath un peu plus compliquées:

 //Etudiant[starts-with(Prenom,'Bernadette')]
 //Participant[string-length(Nom)>=8]
 author [(last() - 4) <= position()) and (position() <= last()
 cours/module[position()=1]/section[position()=2]

XPath est utilisé par d'autres langages, par exemple XQuery et nous allons introduire plus de XPath dans un autre tutoriel... Voir aussi: xml-xpath.html (transparents)

Récapitulatif de chemins simples de localisation XPATH

Pour écrire des règles XSLT simples, il suffit de retenir que XPath fonctionne comme les chemins de fichier sur Unix ou dans les liens HTML.

Elément syntaxique (Type de chemin) Exemple d’un chemin Exemple d’un match réussi par rapport au chemin indiqué à gauche
balise nom d’élément project <project> ...... </project>
/ sépare enfants directs project/title <project> <title> ... </title>
/ (le "tout" du fichier XML, correspond souvent à l’élément racine)
// descendant project//title <project><problem> <title>....</title>
document('autre_doc.xml') à partir d'un autre document xml document('project.xml')/project <project>....</project> (du document xml externe)
//title <racine>... <title>..</title> (n'importe où)
* "wildcard" */title <bla> <title>..</title> et <bli> <title>...</title>
| opérateur "ou" title|head <title>...</title> ou <head> ...</head>
*|/|@* (tous les éléments: les enfants, la racine et les attributs de la racine)
. élément courant .
../ élément supérieur ../problem <project>
@ nom d’attribut @id <xyz id="test">...</xyz>
project/@id <project id="test" ...> ... </project>
@attr=’type’ Identife tous les attributs d'un type (identique à "@")
list[@type=’ol’] <list type="ol"> ...... </list>
position() position de l'élément par rapport au parent position()
last() nombre d'éléments dans un contexte last() position()!=last()

Exemple (simple) d'utilisation de XPath pour contextualiser l'affichage

Grâce à XPath, il est notamment possible de sélectionner certains nœuds selon l'endroit où ils se trouvent dans la fichier XML. Par exemple, imaginons le fichier XML suivant, qui décrit un étudiant rattaché à une faculté.

<etudiant>
  <nom>Dupond</nom>
  <prenom>Jean</nom>
  <faculte>
    <nom>FPSE</nom>
  </faculte>
</etudiant>

La balise nom apparaît deux fois dans des contextes différents et il est probable que l'on veuille l'afficher différemment. Une solution possible serait de construire un code comme

<xsl:template match="etudiant">
	<p>
           <xsl:apply-template select="nom"/>
           <xsl:apply-templates select="prenom"/>
	</p>
	<p>
                <!-- une étape de traitement qui semble inutile pour afficher le nom de la faculté : -->
		<xsl:apply-templates select="faculte" />
	</p>
</xsl:template>

<!-- une ligne qui ne fait essentiellement rien : -->
<xsl:template match="faculte">
		<xsl:apply-templates select="nom" />
</xsl:template>

<!-- deux lignes pour essentiellement la même chose : -->
<xsl:template match="nom">
	<xsl:value-of select="."/>
</xsl:template>

<xsl:template match="prenom">
	<xsl:value-of select="."/>
</xsl:template>

qui est assez long et dont certaines lignes sont relativement pauvres. Avec XPath, on peut récrire tout ca en beaucoup plus court et facile a lire :

<xsl:template match="etudiant">
	<p>
		<xsl:apply-template select="nom"/>
		<xsl:apply-templates select="prenom"/>
	</p>
	<p>
                <!-- on sélectionne directement le nom de la faculté -->
		<xsl:apply-templates select="faculte/nom" />
	</p>
</xsl:template>

<!-- on utilise "|" pour effectuer le même traitement aux nœuds "nom" et "prenom" -->
<xsl:template match="nom|prenom">
	<xsl:value-of select="."/>
</xsl:template>

Dans cet exemple, on a utilisé le sélecteur "faculte/nom" pour sélectionner directement le nœud "nom" qui se trouve à l'intérieur de "faculte", sans avoir besoin de définir un template intermédiaire pour le nœud "faculte". De plus, on utilise les opérateurs de XPath pour ne pas avoir à réécrire inutilement les mêmes instructions pour afficher le nom et le prénom.

Extraction d’une valeur avec XSLT

Extraire la valeur (texte) d'un nœud

Les instructions xsl:value-of et {...}

xsl:value-of sélectionne le résultat d’un XPath et le copie vers le document "sortie". Autrement dit: on peut extraire directement le contenu d’un sous-élément, la valeur d’un attribut, etc. Syntaxe:

  <xsl:value-of select=" ..... "/>

Exemple:

  • La règle suivante se déclenche dès qu’une balise <projet> est trouvée.
  • Elle insère dans le document de sortie le contenu de l’élément <title> qui se trouve à l’intérieur d’un sous-élément <problem>
 <xsl:template match="project">
     <P>
       <xsl:value-of select="problem/title"/>
     </P>
   </xsl:template>

Générer un attribut

syntaxe {...}

Attention: il faut utiliser une autre syntaxe spéciale pour insérer la valeur d’un objet dans la chaîne de caractères d’un attribut à générer:

 {....}
Voici un exemple
<xsl:template match="contact-info">
 ....
  <a href="mailto:{@email} ">
<xsl:value-of select="@email"/></a>
 ...

Dans l'exemple la syntaxe {@email} insère la valeur de l’attribut email de l’élément courant à l'intérieur de l'attribut "href" généré alors que la syntaxe <xsl:value-of select="@email"/> insère la valeur de l'attribut email de l'élément courant à l'intérieur du texte de l'élément A généré.

Grâce à cette syntaxe {@email} on pourra générer par exemple:

<contact-info email="test@test">


La même syntaxe s'utilise pour les cibles dans le document:

<a href="#{test}"></a>

ou hors du document xml courant:

href="document.xml#{text}"

et pour les ancres:

<a name="{test}"/>


xsl:attribute

Une autre technique consiste à utiliser l'élément <xsl:attribute>, pour créer un nœud attribut dans l'élément de sortie ( en l'occurrence ici un élément html).

Dans l'exemple suivant, on indique que l'on veut créer un attribut dont le nom est "src" dans l'élément <img> et on utilise <xsl:value-of> pour sélectionner la valeur à lui associer.

Voici le même exemple
<xsl:template match="contact-info">
 ....
  <a>
   <xsl:attribute name="href">
      mailto:<xsl:value-of select="@email"/>
   </xsl:attribute>
  </a>
 ...

C'est une méthode très générale permettant d'introduire n'importe quel attribut dans un élément et par exemple de combiner la valeur de plusieurs nœuds pour cela.

Ci-dessous, il y a un autre exemple qui introduit un attribut src complexe pour des images hébergées sur un serveur distant.

Fichier XML :
<imagesDistantes>
  <serveur>mon.serveur.com</serveur>
  <image>image1.jpg</image>
  <image>image2.jpg</image>
</imagesDistantes>
Fichier XSL qui reconstruit les URL des images :
<xsl:template match="image">
  <IMG>
    <xsl:attribute name="src">
      http://<xsl:value-of select="/imagesDistantes/serveur" />/<xsl:value-of select="."/>
    </xsl:attribute>
  </IMG>
</xsl:template>

Le code généré par le template "image" sera alors

<IMG src="http://mon.serveur.com/image1.jpg"></IMG>
  • Vous pouvez également créer ainsi plusieurs attributs :

Ci-dessous, il y a un autre exemple qui introduit un attribut "id" et "width" dans un div pour spécifier son nom et sa largeur.

<DIV>
  <xsl:attribute name="id">
    <xsl:value-of select="division/nom" />
  </xsl:attribute>
 
<xsl:attribute name="width">
    <xsl:value-of select="division/taille_image" />
  </xsl:attribute>
</DIV>

xsl:copy

L'instruction xsl:copy

  • Sert à copier "tel quel" un élément source vers le document produit
  • Copie les balises et le contenu !

Scénarios d’usage

  • Utile pour reproduire l’original (ici un tag <p>...</p>)
   <xsl:template match="p">
    <xsl:copy> <xsl:apply-templates/> </xsl:copy>
   </xsl:template>
  • Utile pour récupérer tous les éléments pour lesquels vous n'avez pas défini de règles. Mais attention: Si la balise recopiée ne correspond pas à un tag HTML, rien ne va s'afficher et il faut regarder la source de HTML produite et agir ....
 <xsl:template match="*">
    <xsl:copy>Garbage: <i> <xsl:apply-templates/> </i> </xsl:copy>
   </xsl:template>

Le fragment suivant copie tous les éléments et attributs non traités par les autres templates. C'est une technique utile si vous utilisez beaucoup de balises XHTML dans votre XML et que vous ne désirez pas traiter (par flemme) ou encore si XSLT sert juste à "enrichir" votre code XML (genre table de matières)

 <xsl:template match="*|@*">
   <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:apply-templates select="node()"/>
   </xsl:copy>
  </xsl:template>

A éviter: Il vaut mieux contrôler et écrire une règle explicite pour tout élément qui peut se trouver dans votre XML !

Exemples et cas particuliers

Voici quelques exemples commentés.

Simple XML vers HTML avec XSLT

Code:

Un texte en XML:

 <arbre>
  <para>Simples Templates et XPath</para>
  <aunt>
   <name>Auntie</name>
   <child>Je suis un enfant de aunt</child>
  </aunt>
  <uncle>
   <name>Uncle Ben</name>
   <child>Je suis le premier enfant de uncle</child>
   <child>Je suis le 2eme enfant de uncle</child>
   <child>Je suis le 3eme enfant de uncle</child>
  </uncle>
 </arbre>

La feuille de style XSLT:

Ici on veut produire un simple HTML à partir du XML, avec les consignes suivantes:

  • On aimerait que les enfants de <aunt> et <uncle> soient affichés différemment
  • Le premier enfant de <uncle> doit être affiché spécialement aussi
  • Si voulez savoir comment ce code s’exécute, consultez le fichier ...-trace.xml
  <xsl:template match="arbre">
   <html><title>XSL Example</title><body>
     <xsl:apply-templates />
    </body> </html>
  </xsl:template>

  <xsl:template match="uncle|aunt">
    <hr /> <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="name">
   <xsl:apply-templates /> :
  </xsl:template>

  <xsl:template match="uncle/child[position()=1]">
   <p> <strong><xsl:apply-templates /></strong> </p>
  </xsl:template>
  <xsl:template match="uncle/child[position()>1]">
   <p> <xsl:apply-templates /></p>
  </xsl:template>
  <xsl:template match="aunt/child">
   <p style="color:blue"><xsl:apply-templates /></p>
  </xsl:template>

Le résultat en HTML:

 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
    <title>XSL Example</title>
    <body>
       Simples Templates et XPath
       <hr>
       Auntie :
       <p style="color:blue">Je suis un enfant de aunt</p>
       <hr>
       Uncle Ben :
       <p><strong>Je suis le premier enfant de uncle</strong></p>
       <p>Je suis le 2eme enfant de uncle</p>
       <p>Je suis le 3eme enfant de uncle</p>
    </body>
 </html>

Gestion de liens

Le formalisme XML en soi ne comprend pas les liens ! Il existe un langage XLink que vous pouvez utiliser (et qui fait partie des standards SVG). Sinon, vous inventez un élément ou encore un attribut pour ce type d’information et vous traduisez en <a href ...> ... </a>.

Traduction vers

<a href="...">...</a>:

C.f. le code source de ces fichiers !

Extraits du fichier XML:

  • On peut inventer une balise comme "url" pour l’URL et une autre balise comme "name" pour indiquer le nom du lien.
  <address>
    <name>TECFA</name>
    <url>http://tecfa.unige.ch</url>
   </address>

   <address2>
    <name>TECFA</name>
    <url>http://tecfa.unige.ch</url>
   </address2>

Alternativement, on aurait pu mettre des informations dans un attribut:

   <address4 url="http://tecfa.unige.ch">TECFA</address4>
   <address5 url="http://tecfa.unige.ch">TECFA</address5>

Extraits du fichier XSLT:

Pour address et address2 on crée des règles

 <xsl:template match="address">
   <a href="{url}"> <xsl:value-of select="name "/> </a>
 </xsl:template>

 <xsl:template match="address2">
     <xsl:apply-templates select="url"/>
 </xsl:template>

 <xsl:template match="url">
  <a href="{.}"> <xsl:value-of select="../name"/> </a>
 </xsl:template>

address3 et address2 sont traitées directement depuis l’élément mère

 <a href="{address3/url}"><xsl:value-of select="address3/name"/></a>
 <a href="{address4/@url}"><xsl:value-of select="address4"/></a>
 <xsl:template match="address5">
   <a href="{@url}"> <xsl:value-of select="."/> </a>
 </xsl:template>

Images

Il y n’a aucune magie spéciale pour gérer les images ! Simplement:

  • Examinez votre XML
  • Trouvez un moyen pour traduire en HTML (ou autre chose)

Insertion d’images:

Fichier XML:

 <?xml version="1.0"?>
 <?xml-stylesheet href="images.xsl" type="text/xsl"?>
 <page>
  <title>Hello Here are my images</title>
  <list>
    <image>dolores_001.jpg</image>
    <image>dolores_002.jpg</image>
    <image>dolores_002.jpg</image>
    <image2>scrolls.jpg </image2>
    <image2>scrolls.jpg </image2>
    <image3 source="dolores_002.jpg">Recipe image</image3>
  </list>
  <comment>Written by DKS.</comment>
 </page>

XSLT stylesheet:

  • Une règle pour la balise "list"
<xsl:template match="list">
  Apply templates for "image" elements:
   <!-- lancer la règle -->
   <xsl:apply-templates select="image"/>
   <!-- Va insérer le premier élément "image2" trouvé -->
   <p> <img src="{image2}"/> </p>
   <!-- Gérer l'élément image3 (avec un attribut) -->
    <xsl:apply-templates select="image3"/>
 </xsl:template>

Une règle pour la balise "image" (c.f. ci-dessus )

<xsl:template match="image">
  <p> <img src="{.}"/> </p>
</xsl:template>

Une règle pour la balise "image3"

<xsl:template match="image3">
   <p> <img src="{@source}"/>
      <xsl:value-of select="."/>
   </p>
</xsl:template>

Voyez, il existe pleins de solutions ! Donc on répète: XSLT ne connaît ni HTML ni les images ni quoi que ce soit. C'est vous qui définissez comment un XML va se traduire en HTML !

Gestion d'un nœud selon le contexte : l'attribut "mode"

Souvent il est souhaitable de pouvoir définir plusieurs comportements différents pour le même nœud :

  • quand le type de nœud est utilisé à différents endroits du même document XML ;
  • quand le même nœud doit être affiché plusieurs fois dans le document généré.

Nœud utilisé à des endroits différents du XML

Il y a de nombreux cas où le nœud est utilisé à des endroits différents du fichier XML (par exemple un nœud nom qui serait utilisé pour le nom d'une personne, à afficher en rouge, et pour le nom de sa faculté, à afficher en noir). Dans ces cas, il est souvent préférable de régler le problème avec différents sélecteurs XPath et des templates intermédiaires. Pour cela voir les sections Application de templates aux sous-éléments, XPATH et Exemples et cas particuliers.

Nœud utilisé plusieurs fois dans le fichier XSL

Pour cela, il est souvent nécessaire de modifier radicalement le traitement du nœud. Cela est particulièrement utile lorsque le nœud est complexe (c'est-à-dire composé de plusieurs sous-éléments).

L'attribut mode fonctionne ici comme un sélecteur qui permet de définir plusieurs templates concernant le même nœud (c'est-à-dire avec le même attribut match).

Par exemple, si l'on imagine un fichier XML qui présente un livre avec le titre et l'image de couverture (éléments <titre> et <couverture>). On souhaitera sûrement pouvoir afficher une vignette avec la couverture en petit ainsi qu'une version en grand format. On pourrait utiliser un code comme

<!-- image en petit -->
<img width="100px><xsl:apply-templates select="couverture"/></img>
<!-- image en grand -->
<img width="500px><xsl:apply-templates select="couverture"/></img>

<xsl:template match="couverture">
   <xsl:attribute name="src"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>

Mais cela aurait pour conséquence de séparer le tab img en deux endroits du XSL, ce qui peut devenir problématique en cas de modification ultérieure du document.

La solution alternative avec mode permet de faciliter les modifications ultérieures :

<!-- l'image en petit -->
<xsl:apply-template select="couverture" mode="petit" />
<!-- l'image en grand -->
<xsl:apply-template select="couverture" mode="grand" />

<xsl:template match="couverture" mode="petit">
    <img width="100px" src="{.}"/>
</xsl:template>

<xsl:template match="couverture" mode="grand">
    <img width="500px" src="{.}"/>
</xsl:template>

Exemple d'utilisation : fabrication de références (liens)

Table des matières pour éléments qui ont un identificateur:

On utilise ici un attribut "mode" dans la définition des templates et apply-templates

  • Cela nous permet d’écrire plusieurs règles pour un même nœud
  • Ici par exemple, on utilise mode="toc" pour fabriquer une table des matières

Fragment XSLT (fait d’abord la table des matières, ensuite le reste)

 <xsl:template match="/">
   <html>
    <body bgcolor="#FFFFFF">
      <h1><xsl:value-of select="/RECIT/Titre"/></h1>
      <p> Highlights de l'histoire:

          <xsl:apply-templates select="//EPISODE" mode="toc"/> </p>

      <xsl:apply-templates/>
    </body>
  </html>
 </xsl:template>

Fragments XSLT pour gérer la balise "EPISODE": 2 règles dont une avec un mode

 <xsl:template match="EPISODE" mode="toc">
   <a href="#{@id}"> <xsl:value-of select="SousBut"/> </a> -
 </xsl:template>
 
<xsl:template match="/RECIT/FIL/EPISODE">
   <a name="{@id}"> <hr /> </a>
   <xsl:apply-templates/>
 </xsl:template>

Tables des matières pour éléments sans ID

Plus difficile car il faut "fabriquer" des attributs "name" et "href" pour le HTML

  • la solution adoptée ici est moche et à refaire (on aurait pu compter les éléments)
  • il s’agit des jours d’un atelier webmaster qu’on peut consulter ici:
  • http://tecfa.unige.ch/tecfa/teaching/formcont/webmaster2003/programme/
  • Pour comprendre cet exemple il faut fouiller dans les fichiers suivants:
    • programme.xml - contient tout le "programme" de l’Atelier
    • programme.xsl - produit le résultat (voir le fichier programme.html)
    • matos.xsl, resume.xsl, animateurs.xsl créent des extraits variés du programme.

Fragments XSLT

 <!-- Code qui fabrique la table des matières (jours) en HTML -->
 Programme: <xsl:apply-templates select="//day" mode="toc"/>

 <xsl:template match="day" mode="toc">
   <a href="#{@name}{@dayno}{@month}"
 ><xsl:value-of select="@name"/></a> -

 </xsl:template>
 <!-- Code pour insérer des attributs "name" dans le HTML -->
 <xsl:template match="day">
    <a name="{@name}{@dayno}{@month}" >
    <xsl:value-of select="@name"/></a> - 
    <xsl:value-of select="@dayno"/>/<xsl:value-of select="@month"/>/
    <xsl:value-of select="@year"/>
 </xsl:template>

Fragment XML (élément à extraire)

Faire une table des matières avec les jours de l’Atelier (avec liens)

<day name="lundi" year="2003" month="6" dayno="16">

Résultat HTML

Au début du fichier on a un menu qui affiche les jours (liens vers le bas)

Programme: <a href="#lundi166">lundi</a> - <a href="#mardi176">mardi</a> - ....
......
  • Dans le fichier on insère les attributs "name"
<a name="lundi166">lundi</a> - 16/6/2003

Note: Dans ce répertoire il y a aussi un fichier programme-fo.xsl qui génère du code xsl-fo utilisé pour générer la version PDF du programme.

Tables des matières pour éléments sans ID

Variables et templates avec paramètres

Il possible en XSLT de définir des variables (attention il s'agit en fait de constantes, car leur valeur n'est pas modifiable) ainsi que de faire passer des paramètres aux templates. Cela permet un traitement modulable des nodes.

xsl:variable

La syntaxe d'une "variable" en XSLT est

 <xsl:variable name="nom" select="expression"> Contenu </xsl:variable>
  • Si l'attribut select est présent, alors le contenu Contenu doit être vide.
  • l'attribut select peut faire référence à un nœud, dans ce cas la variable prendra la valeur du contenu du nœud ;
  • l'attribut select peut faire référence à un attribut (référencé par @nom_attribut), dans ce cas la variable prendra la valeur du contenu de l'attribut;
  • l'attribut select peut faire référence à une chaîne de caractères (entre guillemets simples), dans ce cas la variable prendra la valeur de la chaîne ;
  • l'attribut select peut faire même référence à une autre variable (référencée par $nom_variable), dans ce cas la variable prendra la valeur de la variable indiquée ;
  • Si le nœud, l'attribut ou la variable indiquée n'existe pas, la variable prendra la valeur d'une chaîne de caractères vide ("").

Souvenez-vous, il n'est pas possible de modifier la valeur d'une variable après son attribution !


Référence à une variable Pour faire référence à une variable il suffit de faire précéder son nom par $.

Une variable appelée url peut être définie par

 XML : <url>www.google.com</url>
 XSL: <xsl:variable name="url" select="url"/>
 ou   <xsl:variable name="url"><xsl:value-of select="url"/></xsl:variable>

et peut être utilisée par exemple par

  <a href="http://{$url}">$url</a>

Pour une autre utilisation des variables, voir le Tutoriel XSLT pour générer du SVG.

xsl:param et xsl:with-param

On peut également utiliser des paramètres dans les template.

déclaration d'un paramètre dans un template : xsl:param Cela fonctionne comme les variables à l'exception du fait que les valeurs peuvent être définies lors de l'appel du template (donc modifiées par le template appelant).

Pour définir un paramètre dans un template on utilise le code

 <xsl:param name="nom" select="valeur par défaut" />

La valeur par défaut n'est pas obligatoire. Dans le cas où elle est omise en revanche on sera contraint d'appeler le template en spécifiant toujours une valeur pour le paramètre.

attribution d'une valeur au paramètre : xsl:with-param Lors de l'appel par un autre template, il faut spécifier la valeur du paramètre (sauf si on veut utiliser la valeur par défaut) comme suit :

 <xsl:apply-templates select="un_selecteur_XPath">
   <xsl:with-param name="nom_paramètre" select="valeur_du_paramètre" />
 </xsl:appy-templates>

Par exemple, lors d'un environnement multilingue, on peut avoir un fichier XML comme suit

<doc>
 <titre>
  <en>The Title</en>
  <fr>Le Titre</fr>
 </titre>
</doc>

Pour n'afficher que les informations en français (nœud fr) on utilise donc

 <xsl:apply-templates select="titre">
    <!-- on sélectionne la langue française -->
    <xsl:with-param name="lang" select="'fr'" />
 </xsl:apply-templates>

 <xsl:template match="titre"> 
   <!-- langue affichée : par défaut l'anglais -->
   <xsl:param name="lang" select="en" />
   <xsl:value-of select="$lang" />
</xsl:template>

Déclarations et style

Veillez à ce que le fichier produit corresponde aux normes, c.à.d. qu’il contienne les déclarations nécessaires pour chaque type de document.

xsl:output

permet de définir le type de sortie qui sera produit et de générer des entêtes. Voici la syntaxe (simplifiée) pour XSL V 1.0 (1999):

<xsl:output> 
 method = "xml" | "html" | "text"
 version = nmtoken
 encoding = string
 omit-xml-declaration = "yes" | "no"
 standalone = "yes" | "no"
 doctype-public = string
 doctype-system = string
 indent = "yes" | "no"
 media-type = string
 />
  • A mettre au début du fichier (après xsl:stylesheet)
  • Ci-dessous quelques exemples

Output en HTML 4.01 transitionnel

 <xsl:output method="html" 
      doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>

Output en XHTML "façon light"

 <xsl:output
    method="html"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    indent="yes"
 />

Output en XHTML "pur" (page XML) et transitionnel

 <xsl:stylesheet version="1.0"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns="http://www.w3.org/1999/xhtml">
 <xsl:output
    method="xml"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    indent="yes"
 />

Output en XHTML "pur" et strict

 <xsl:stylesheet version="1.0"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns="http://www.w3.org/1999/xhtml">
 <xsl:output
    method="xml"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    indent="yes"
    encoding="UTF-8"
 />

Output en SVG

 <xsl:output
  method="xml"
  indent="yes"
  standalone="no"
  doctype-public="-//W3C//DTD SVG 1.0//EN"
  doctype-system="http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd"
  media-type="image/svg"
 />


Output en HTML5

HTML5 est plus délicat, puisque la spécification XSLT a été créée avant HTML5. Comme HTML5 n'est ni SGML ni XML, il n'existe pas de solution élégante .....

Example - Output en HTML 5
<xsl:output
     method="html"
     doctype-system="about:legacy-compat"
     encoding="UTF-8"
     indent="yes" />

 <xsl:template match="/">
   <html>
     <head>
       <meta charset="utf-8"/>
       <title>HTML5 + SVG example</title>
     </head>
     <body>
 .....
         </body>
 </html>

On peut aussi produire du XML, mais ensuite enlever l'entête XML ....

<xsl:output
     method="xml"
     omit-xml-declaration = "yes"
     encoding="UTF-8"
     indent="yes" />

 <xsl:template match="/">

   <html>
   <xsl:text disable-output-escaping="yes">
<![CDATA[<!DOCTYPE html>]]>
   </xsl:text>
     <head>
       <meta charset="utf-8"/>
       <title>HTML5 + SVG example</title>
     </head>
     <body>
 .....
         </body>
 </html>
Example - sérialisation en XHTML5

Voici la meilleure solution:

<xsl:output
     method="xml"
     omit-xml-declaration = "yes"
     doctype-system="about:legacy-compat"
     encoding="UTF-8"
     indent="yes" />

ou encore:

<xsl:output
     method="xml"
     doctype-system="about:legacy-compat"
     encoding="UTF-8"
     indent="yes" />

Autre méthode (ne marche pas dans Firefox 19)

<xsl:output
     method="xml"
     encoding="UTF-8"
     indent="yes" />

<xsl:template match="/">
   <xsl:text disable-output-escaping="yes">
<![CDATA[<!DOCTYPE html>]]>
   </xsl:text>
   <html xmlns="http://www.w3.org/1999/xhtml">
     <head>...</head>
     <body>.....</body>
    </html>

Output en VRML

 <xsl:output method="text"
  encoding="UTF-8"
  media-type="model/vrml"/>
 ....

 <xsl:template match="/">#VRML V2.0 utf8

 ......

CSS pour le résultat de la transformation

Lorsque vous produisez du HTML ou du XHTML, évitez de produire du HTML "vieille école" (balises "font", etc.). Il est simple d’associer une feuille de style CSS ! Vous "faites" comme à la main. Donc il faut insérer la balise "link" à l’endroit ou le <head> est généré.

<xsl:template match="racine">
<html>
<head>
 <link href="programme.css" type="text/css" rel="stylesheet"/>

<title>
bla bla

</title>
</head>

Générer plusieurs fichiers HTML à partir d’un seul XML

Marche uniquement lorsqu’on traite le fichier XML en "batch"

Programme de l’Atelier WebMaster 2004

 <!-- au début du fichier -->
 <xsl:output name="daypage" method="html"      doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
 .....

 <!-- une règle qui génère une page -->
  <xsl:template match="software">
   <xsl:result-document href="software.html" format="daypage">

   <html> <head>
     <title> <xsl:value-of select="/course/course-title"/>	 </title> </head>
     <body bgcolor="white">
      [<a name="top" href="../welcome.html">Home</a>] -&amp;gt; [<a name="top" href="programme.html">Programme</a>] -&amp;gt; [Logiciels]

      <ul>
       ......

       <xsl:apply-templates select="soft"/>
      </ul>
     </body>
    </html>
  
  </xsl:result-document>

  </xsl:template>

Quelques astuces:

Si vous devez générer plusieurs pages pour un élément du même nom, il faut générer des noms de fichiers uniques:

 <xsl:template match="day">
   <xsl:result-document href="{@name}{@dayno}{@month}.html" format="daypage">

Dans l’exemple présent, on désire avoir une page / jour du programme. Chaque jour se distingue par une date spéciale (attributs dayno et month)

Pour faire une table des matières (que vous pouvez inclure partout):

  • Voici la règle qui génère la table:
 <xsl:template match="day" mode="toc">
   <a href="{@name}{@dayno}{@month}.html"><xsl:value-of select="@name"/></a> -

 </xsl:template>

Voici comment l’inclure:

Programme: <a href="programme.html"> Top</a> - <xsl:apply-templates select="//day" mode="toc"/>

XSLT en "batch" et debugage

Il faut apprendre à utiliser XSLT en "batch" pour plusieurs raisons. La plus importante est de pouvoir valider le HTML produit. Enfin, il existe aussi des extensions pour les navigateurs FireFox et IE qui permettent de voir le code HTML généré.

Avec un fichier de commande

Il existe plusieurs processeurs XSLT populaires qu’on peut utiliser pour produire un fichier de sortie à partir d’un xml + xslt. On conseille Saxon (ci-dessous)

  • Il faut passer par un processeur XSLT pour "déboguer" une feuille de style XSLT client-side
  • "View source" dans un navigateur ne montre pas le HTML !
  • Donc maîtriser une "procédure manuelle" est intéressant !!
  • Alternativement, il existe des outils de débogage pour certains éditeurs.

Certains outils nécessitent l’installation d’un environnement Java.

  • il faut installer un runtime ou un Java development Kit pour utiliser les processeurs Xalan ou Saxon.
  • Un engin Runtime ("JRE") suffit, à télécharger (si nécessaire) depuis http://java.sun.com/products/

Avec un éditeur XML (solution conseillée pour les débutants)

La plupart des éditeurs XML ont un processeur XSLT intégré (les versions commerciales ont des fonctions de débogage).

Dans XML Exchanger light, utilisez le menu Transform pour produire un HTML que vous pouvez ensuite valider.

  • Ouvrir le fichier XML ou le tab si c'est déjà fait (pas XSLT !)
  • Menu Transform
  • Execute Advanced XSLT
    • Cliquer sur "current" dans Input"
    • Cliquer sur Use Processing Instructions dans XSL
    • Output to New Document (ou File)

Ensuite, validez votre HTML

XSLT avec PHP 5

Le support XSLT est standard dans PHP 5. L’exemple ci-dessous applique une feuille de style travaux.xsl au fichier travaux.xml

 $xml_file = ’travaux.xml’;
 $xsl_file = ’travaux.xsl’;

 // load the xml file (and test first if it exists)
 $dom_object = new DomDocument();
 if (!file_exists($xml_file)) exit(’Failed to open $xml_file’);
 $dom_object->load($xml_file);
 // create dom object for the XSL stylesheet and configure the transformer
 $xsl_obj = new DomDocument();
 if (!file_exists($xsl_file)) exit(’Failed to open $xsl_file’);
 $xsl_obj->load($xsl_file);
 $proc = new XSLTProcessor;
 $proc->importStyleSheet($xsl_obj); // attach the xsl rules
 $html_fragment = $proc->transformToXML($dom_object);
 print ($html_fragment);

Donc pour utiliser ce "service", il suffit de copier le fichier php-xslt.php et changer les 2 noms de fichiers (travaux.xml et travaux.xsl) au début
(enfin depuis le web il faut prendre php-xslt.text et le renommer en xxx.php)

Client-side XML+XSLT avec Firefox 1.0+ ou IE6+

XSLT fonctionne sans problème avec les navigateurs IE, Mozilla/Firefox et Opera. Par contre, certains navigateurs comme Chrome refusent d'exécuter une page XML en local. Il faut la déposer sur un serveur.

Un simple exemple

Pour assurer que la sortie soit accepté comme HTML, il faut ajouter au moins la déclaration suivante (méthode de sérialisation), mais on conseille de faire une déclaration complète, déposer les fichiers sur un serveur et de tester la solution avec tous les navigateurs.

<xsl:output method="html"/>
  • Voir les fichiers pour les détails. Si aucun contenu n’est affiché ou s’il est mal affiché, faites "Menu->View->Source"

Note: Il faut s’assurer que le serveur Web indique le bon mime type pour xml et xsl (text/xml). Ceci est fait à Tecfa, mais pas forcément chez votre fournisseur....

Executive summary

(1) Créer une feuille XSLT xxx.xsl

(2) Copier/coller le code ci-dessous:

<?xml version="1.0" ?>
 <xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 </xsl:stylesheet>

(3) Écrire une règle qui gère la racine. Cette règle doit produire l'entête, racine, head et body du HTML.

 <xsl:template match="page">
   <html>
   <head> <title> <xsl:value-of select="title"/> 
 </title> </head>
   <body bgcolor="#ffffff">
      <xsl:apply-templates/>
   </body>
   </html>
 </xsl:template>

(3) Écrire une règle pour chaque élément XML

  • Pour chaque règle il faut insérer (produire) soit du HTML, soit du texte, souvent les deux et finalement parfois rien du tout.
  • Il faut un <xsl:apply-templates> (ou équivalent) dans chaque règle, sauf si vous désirez censurer le contenu

(4) Associer cette feuille de style avec un fichier XML

  <?xml-stylesheet href="xxx.xsl" type="text/xsl"?>

Liens

Transparents
Anglais

XSL reference card liste des éléments XSLT