Tuteur pour le langage XML : exemples détaillés (partie 2 / 3)
Texte du Tuteur écrit par Gilles HUNAULT
Liste des autres tuteurs (langages, logiciels, systèmes d'exploitations...)
Dans ce document :
retour à la table des matières principales1. Exemples simples de documents XML
2. Exemples simples de grammaires DTD
3. Exemples simples de schémas XSD
4. Exemples didactiques de transformations XSL
5. Exemples réels de documents, grammaires et transformations
1. Exemples simples de documents XML
Nous allons montrer ici en détail comment écrire des documents XML, les DTD et les XSD (schémas) qui vont avec ainsi que des fichiers XSL pour transformer ces textes en documents prêts à l'emploi. Un premier exemple sera celui d'algorithmes, c'est à dire des fichiers textes qui contiennent des instructions, comme
# algorithme élémentaire écrire bonjour écrire "combien de gateaux voulez-vous ? " lire nbGato écrire " merci, au revoir."
Un deuxième exemple sera celui de la description de variables statistiques, comme par exemple
/* variables du dossier ENQUETE SOCIALE */ /* format ID : identifiant */ /* format QT : nom unité min max */ /* format QL : nom nb_modalités labels_modalités */ ID MATRI # matricule QT AGE années 0 100 QL SEXE 3 NR homme femme QT EMPLOI 4 NR actif retraité inactif QT SALAIRE mega-euros 0 100 QL MARIAGE 3 NR oui non QT FAMILLE personnes 0 10
Ce fichier de description de variables est couplé à des fichiers de données comme par exemple
H001 30 1 1 3 0 3 F002 25 2 1 2 0 2 ...
Le choix des balises et de leurs attributs est la partie la plus délicate. Ainsi une balise de commentaire pour un algorithme peut se coder de façon succinte par
<cmt> exemple élémentaire : </cmt> <cmt> on demande un nombre de ... et on en déduit... </cmt>
Mais rien n'interdit d'avoir des commentaires plus structurés. Par exemple il arrive qu'on travaille à plusieurs sur un même document, que certains commentaires indiquent des parties (et servent de titre) alors que d'autres commentaires servent de documentation ponctuelle. On peut alors avoir plusieurs "géométries" pour les balises commentaires, comme par exemple :
<cmtTitre> exemple élémentaire : </cmtTitre> <cmt auteur="gH"> mise à jour du 08/01/2017 </cmt> <cmt><auteur>gH</auteur><titre>partie 1</titre>"> mise à jour du 08/01/2017 </cmt> <cmt><niveau>détail</niveau> on demande un nombre de ... et on en déduit... </cmt>
Admettons dans un premier temps qu'on définisse des balises sans attribut et sans caractères accentués à savoir <algorithme>, <cmt>, <ecrire> et <lire>. Le document XML correspondant à l'algorithme qui nous sert d'exemple sera alors
<?xml version="1.0" ?> <algorithme> <cmt> exemple 1 </cmt> <ecrire> bonjour </ecrire> <ecrire> combien de gateaux voulez-vous ? </ecrire> <lire> nbGato </lire> <ecrire> merci, au revoir. </ecrire> </algorithme>
Si on veut utiliser des balises accentuées comme <écrire> il faut utiliser l'attribut d'encodage de la balise <?xml, soit par exemple le texte
<?xml version="1.0" encoding="ISO-8859-1" ?> <algorithme> <cmt> exemple 2 </cmt> <écrire> bonjour </écrire> <écrire> combien de gateaux voulez-vous ? </écrire> <lire> nbGato </lire> <écrire> merci, au revoir. </écrire> </algorithme>
Pour insister sur le fait qu'une demande ne se fait pas avec la seule instruction LIRE mais qu'elle se fonde sur une question et une réponse, on pourra mettre explicitement une balise de DEMANDE :
<?xml version="1.0" encoding="ISO-8859-1" ?> <algorithme> <cmt> exemple 2 </cmt> <écrire> bonjour </écrire> <demande> <écrire> combien de gateaux voulez-vous ? </écrire> <lire> nbGato </lire> </demande> <écrire> merci, au revoir. </écrire> </algorithme>
On a les memes difficultés de choix de balises les variables statistiques. Ainsi on peut coder les descriptions par
<varID> MATRI <desc>matricule</desc> </varID> <varQT> AGE <unité>années</unité> <min>0</min> <max>100</max> </varQT> <varQL> SEXE <nbmodalités>3</nbmodalités> <modalité>NR</modalité> <modalité>homme</modalité> <modalité>femme</modalité> </varQL> <varQT> SALAIRE <unité>mega-euros</unité> <min>0</min> <max>100</max> <varQL> QL MARIAGE <nbmodalités>3</nbmodalités> <modalité>NR</modalité> <modalité>oui</modalité> <modalité>non</modalité> </varQL> </varQT> <varQT> FAMILLE <unité>personnes</unité> <min>0</min> <max>10</max> </varQT>
ou bien par
<var type="ID" nom="MATRI" desc="matricule" /> <var type="QT" nom="AGE" unité="années" min="0" max="100" /> <var type="QL" nom="SEXE" nbmod="3" mods="NR homme femme" /> <var type="QT" nom="EMPLOI" nbmod="4" mods="NR actif retraité inactif" /s <var type="QT" nom="SALAIRE" unité="mega-euros" min="0" max="100" /> <var type="QL" nom="MARIAGE" nbmod="3" mods="NR oui non" /> <var type="QT" nom="FAMILLE" unité="personnes" min="0" max="10" />
ou encore par (extrait)
<varQL> <nom>SEXE</nom> <nbmodalités>3</nbmodalités> <modalité val="0">NR</modalité> <modalité val="1">homme</modalité> <modalité val="2">femme</modalité> </varQL> <varQT nomQT="SALAIRE"> <unité>mega-euros</unité> <min>0</min> <max>100</max> </varQT>
Pour le choix des éléments et attributs et donc sur la grammaire qui en découlera, on trouvera quelques conseils sur le site selfhtml.
Un premier point important à se rappeler est que contrairement aux bases de données XML permet les contenus mixtes : dans une implémentation oriéntée bases de données de salles de cinéma, on aura une base SALLESCINE avec des tables SALLES, FILMS, ARTISTES... avec XML on pourra avoir trois balises principales SALLES, FILMS, ARTISTES et le document global contiendra l'équivalent de l'ensemble des trois tables. Un deuxième point important à se rappeler est que XML permet de contraindre les documents à etre bien écrits et que les grammaires peuvent servir de garde-fous. Il peut y avoir une cellule vide dans une feuille Excel en face d'un service parce qu'on a oublié de mettre le nom du responable par exemple (ou parce qu'on pensait qu'on le ferait plus tard). Excel ne "réclamera" pas de valeur. Par contre, si le document XML est utilisé avec une grammaire qui interdit les valeurs manquantes on ne pourra pas utiliser le document tant qu'il sera incomplet (on peut bien sur contourner le problème en mettant "toto" ou "?" pour forcer la valeur à ne pas etre vide mais alors cela ne sert à rien de définir des grammaires. En d'autres termes, une grammaire et l'outil logiciel de validation associé à la grammaire remplacent un programme de validation des données.
2. Exemples simples de grammaires DTD
Essayons maintenant de définir une DTD. Là encore, prenons pour l'instant une solution minimaliste : un algorithme est une suite (éventuellement vide) de balises <cmt>, <ecrire> et <lire> prises dans n'importe quel ordre et qui ne sont que des chaines de caractères. Le fichier DTD correspondant sera
<!ELEMENT algorithme (cmt|ecrire|lire)* > <!ELEMENT cmt (#PCDATA) > <!ELEMENT ecrire (#PCDATA) > <!ELEMENT lire (#PCDATA) >
Affinons la DTD : regroupons les balises <cmt>, <ecrire> et <lire> en une balise <ligneAlgo> et indiquons qu'après <lire> on doit impérativement trouver une chaine de caractères et qu'un algorithme n'est jamais vide :
<!ELEMENT cmt (#PCDATA) > <!ELEMENT ecrire (#PCDATA) > <!ELEMENT lire (#PCDATA) REQUIRED > <!ELEMENT ligneAlgo (cmt|ecrire|lire) > <!ELEMENT algorithme (ligneAlgo)+ >
Si maintenant nous essayons de construire des balises plus réalistes, on doit par exemple indiquer que <lire> doit lire une variable. On peut penser aux deux syntaxes suivantes :
<lire> <var> nomDelaVariable </var> </lire> <lire var="nomDelaVariable" />
Dans le premier cas, comme on imbrique la balise <var> dans la balise <lire>, la DTD comportera en remplacement de la ligne de définition de l'élément lire les deux lignes
<!ELEMENT lire (var)> <!ELEMENT var (#PCDATA)>
Dans le deuxième cas, on vient seulement ajouter l'attribut var à la balise <lire> et la DTD devra comporter
<!ELEMENT lire EMPTY> <!ATTLIST lire var CDATA #REQUIRED>
3. Exemples simples de schémas XSD
Le XSD (schéma) qui correspond à la grammmaire minimaliste pour les algorithmes est
<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="algorithme"> <xsd:complexType> <xsd:sequence> minOccurs=0 maxOccurs="unbounded" <xsd:choice cmt lire ecrire /> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="cmt" type="xsd:string"/> <xsd:element name="ecrire" type="xsd:string"/> <xsd:element name="lire" type="xsd:string"/>
Pour indiquer que <lire> doit lire une variable on utilisera le schéma
<xsd:element name="lire" type="lireType"/> <xsd:complexType name="lireType"> <xsd:sequence> <xsd:element ref="var"/> </xsd:sequence> </xsd:complexType> <xsd:element name="var" type="xsd:string"/>
à moins qu'on ne préfère la forme plus compacte
<xsd:element name="lire"> <xsd:complexType> <xsd:sequence> <xsd:element ref="var"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="var" type="xsd:string"/>
et pour la forme avec attribut, on écrira :
<xsd:element name="lire"> <xsd:complexType> <xsd:attribute name="var" type="xsd:string" use="required"/> </xsd:complexType> </xsd:element>
4. Exemples didactiques de transformations XSL
4.1 Transformations élémentaires
4.1.1 Une transformation ... vide
Pour bien comprendre qu'il y a des règles par défaut, il faut commencer par effectuer une transformation qui ne semble ne rien faire. Par exemple si on applique au document XML suivant nommé test3.xml
<?xml version="1.0" encoding="ISO-8859-1" ?> <personnes> <personne> <nom>Dupond</nom> <service>Achats</service> </personne> <personne> <nom>Durand</nom> <service>Achats</service> </personne> <personne> <nom>Dupuis</nom> <service>Courrier</service> </personne> </personnes>la transformation définie par le fichier XSL suivant nommé vide.xsl
<?xml version="1.0" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="ISO-8859-1" /> </xsl:stylesheet>alors on obtient
<?xml version="1.0" encoding="ISO-8859-1"?> Dupond Achats Durand Achats Dupuis CourrierQuelques explications sont nécessaires : l'en-tete <?xml est produite par le processeur XSL à cause de l'indication <xsl:output method="xml". Toutes les autres lignes (y compris les lignes vides) sont liées aux déclenchement de règles par défaut, à savoir : pour chaque élément on affiche son contenu, pour chaque attribut on n'affiche rien. Ce qui permet de comprendre pourquoi,si on applique la transformation vide.xsl au fichier
<?xml version="1.0" encoding="ISO-8859-1" ?> <stage sujet="Etude sur la commercialité intramédicale" an="2035" categorie="gp"> <stagiaire><nom>DUPON</nom> <prenom>Jean</prenom></stagiaire> <entreprise nom="CHU Belle-Beille" mds="Mr ZOUAVE" adr_rueetc="3 rue Pomme" adr_codepost="49000" adr_fincp="Angers" telent="0241024100" /> </stage>on obtient seulement
<?xml version="1.0" encoding="ISO-8859-1"?> DUPON JeanOn pourra lire sur le site selfhtml une introduction soignée et en français à XSLT.
4.1.2 Une transformation XSL qui ne garde que les titres
On dispose d'un fichiers de films de cinéma nommé films.xml dont voici le début
<?xml version="1.0" encoding="ISO-8859-1"?> <FILMS> <FILM Annee='1958'> <TITRE>Vertigo</TITRE> <GENRE>Drame</GENRE><PAYS>USA</PAYS><MES idref="3"></MES> <ROLES> <ROLE><PRENOM>James</PRENOM><NOM>Stewart</NOM> <INTITULE>John Ferguson</INTITULE></ROLE><ROLE><PRENOM>Kim</PRENOM> <NOM>Novak</NOM> <INTITULE>Madeleine Elster</INTITULE></ROLE></ROLES> <RESUME>Scottie Ferguson, ancien inspecteur de police, est sujet au vertige depuis qu'il a vu mourir son collègue. Elster, son ami, le charge de surveiller sa femme, Madeleine, ayant des tendances suicidaires. Amoureux de la jeune femme Scottie ne remarque pas le piège qui se trame autour de lui et dont il va être la victime... </RESUME> </FILM> <FILM Annee='1979'> <TITRE>Alien</TITRE> <GENRE>Science-fiction</GENRE><PAYS>USA</PAYS><MES idref="4"></MES> <ROLES> <ROLE><PRENOM>Sigourney</PRENOM><NOM>Weaver</NOM> <INTITULE>Ripley</INTITULE></ROLE></ROLES> <RESUME>Près d'un vaisseau spatial échoué sur une lointaine planète, des Terriens en mission découvrent de bien étranges "oeufs". Ils en ramènent un à bord, ignorant qu'ils viennent d'introduire parmi eux un huitième passager particulièrement féroce et meurtrier. </RESUME> </FILM> ...On veut écrire une transformation qui n'affiche que les titres des films. On met dans le fichier titres.xsl les instructions pour chercher à partir de la racine tous les titre de films ; pour chaque titre on n'affichera que son contenu. Voici le squelette du programme :
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" encoding="ISO-8859-1" /> <xsl:template match="/"> <xsl:apply-templates select="//TITRE" /> </xsl:template> <xsl:template match="TITRE"> <p><xsl:value-of select="." /></p> </xsl:template> </xsl:stylesheet>Pour utiliser cette transformation titres.xsl comme feuille de style et produire un vrai document HTML, il suffit d'habiller la règle sur la racine avec les balises HTML de définition de document et de mettre autour de la règle sur le titre de quoi séparer les films, soit le texte :
<?xml version="1.0" encoding="ISO-8859-1"?> <!-- la ligne suivante doit être avant la balise xsl:stylesheet --> <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" encoding="ISO-8859-1" /> <xsl:template match="/"> <html> <head> <titre> les titres de films en HTML via XML </titre> </head> <body> <h1>Voici la liste des films </h1> <blockquote> <xsl:apply-templates select="//TITRE" /> </blockquote> </body> </html> </xsl:template> <xsl:template match="TITRE"> <p><xsl:value-of select="." /></p> </xsl:template> </xsl:stylesheet>On peut ensuite modifier le document XML pour obtenir un vrai document HTML converti à la volée par le navigateur. Voici ce qu'il faut modifier :
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/xsl" href="titres.xsl"?> <FILMS> <FILM Annee='1958'> <TITRE>Vertigo</TITRE> <GENRE>Drame</GENRE><PAYS>USA</PAYS><MES idref="3"></MES> <ROLES> ...Vous pouvez tester le résultat via le fichier titres.xml et ... surprise, vous aurez par contre tout le texte des films si vous consultez la source de la page affichée.
Si par contre la transformation doit être faite par le serveur, on utilisera un script PHP comme
<?php $nomXml = "titres.xml"; $nomXsl = "titres.xsl"; $xsl = new XSLTProcessor(); $xsl->importStyleSheet(DOMDocument::load($nomXsl)); echo $xsl->transformToXML(DOMDocument::load($nomXml)); ?>
ou une exécution de programme avec passage des noms de fichiers en paramètre, comme
W:\Xml_Xsl\Exemples>xsltproc.exe titres.xml titres.xsl
ou
/home/gh/Cours/Exemples_xsl>exsl titres.xml titres.xsl
en fonction du "processeur" XSLT utilisé.
4.2 Une transformation XSL qui compte les films
Reprenons le même fichier de films. On veut maintenant compter le nombre de films sachant qu'il y a autant de films que de titres de films. Voici ce qu'on peut écrire si on connait la fonction count() :
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="ISO-8859-1" /> <xsl:template match="/"> On a vu <xsl:value-of select="count(//TITRE)" /> films. </xsl:template> </xsl:stylesheet>Si par contre vous êtes plus à l'aise avec les parcours de noeuds et leur position, vous pouvez écrire pour obtenir le même résultat :
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="ISO-8859-1" /> <xsl:template match="/"> On a vu <xsl:for-each select="//TITRE"> <xsl:if test="position() = last()"> <xsl:value-of select="position()" /> </xsl:if> </xsl:for-each> films. </xsl:template> </xsl:stylesheet>Vous pouvez tester le résultat via le fichier nbfilms.xml
4.3 Approfondir les transformations XSL
Une transformation XSL ne s'écrit pas de la même façon suivant qu'on manipule des éléments ou des attributs. De plus on est parfois amené à sélectionner des noeuds éloignés par référence. Comme XPATH utilise le contexte des noeuds pour évaluer les expressions à l'aide d'éléments XSLT, d'opérateurs XPATH et de fonctions XPATH, il faut un certain temps pour maitriser les "axes" et filtrages XPATH nommés
self child parent ancestor descendant following preceding preceding-sibling following-sibling attribute namespace
car il y a de nombreux raccourcis, abbréviations et sous-entendus dans la désignation de ces axes pour travailler en relatif ou en absolu comme avec les noms de fichiers dans les répetroires.
Voici par exemple un petit tableau de notations courtes et longues fourni par B. Amann et P. Rigaux dans leur livre Comprendre XSLT qui utilise abondamment un fichier XML de films, disponible à l'adresse cnam/thion.
Court Long . self::node() .. parent::node() @ attribute:: @att attribute::att @* attribute::* A/@* child::A/attribute::* [axe par défaut] child:: /A /child::A A/* child::A/child::* [étape par défaut] descendant-or-self::node() // /descendant-or-self::node()/ .// self::node()/descendant-or-self::node()/ A//B child::A/descendant-or-self::node()/child::BVous pourrez peut-être y découvrir ce que signifie
FILMS/ARTISTE[@id=/FILMS/FILM[TITRE='Alien']/MES/@idref]/ACTNOM
On consultera la page xmpxml.htm pour des variations sur le thème éléments/attributs ainsi que des exemples de "vraie" programmation semi-graphique en XSL et un calcul de moyenne en XSL. On y trouvera des utilisations d'axes et d'étapes comme
<xsl:template match="service[not(preceding::service=current())]"> <xsl:value-of select="count(//personne[@nom])"/> <xsl:call-template name="baton"> <xsl:with-param name="val" select="count(//COEF[. = $i])"/> <xsl:with-param name="text" select="concat('Coef = ',$i)"/> <xsl:variable name="long" select="$val div $max * 100"/> <table width="100%"> <tr> <td width="{$long}%" bgcolor="red"/> <xsl:template name="max"> <xsl:param name="noeuds"/> <xsl:param name="m">0</xsl:param> <xsl:choose> <xsl:when test="count($noeuds)=0"> <xsl:value-of select="$m"/>Avant de finir cette section voici un court programme XSL instructif nommé maju.xsl qui transforme avantmaju.xml en apresmaju.xml.
<?xml version="1.0" encoding="ISO-8859-1" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Cette transformation convertit tous les contenus-textes en majuscules, que ce soit dans les éléments ou dans les attributs, en gardant la même structure que le xml source. - le premier "template" recopie les noeuds, - le deuxième template recopie les attributs et transforme le texte en majuscule, - le troisième transforme le texte en majuscule. La passage en majuscules se fait forcément via translate. --> <xsl:output method="xml" indent="yes"/> <xsl:template match="*"> <xsl:copy> <xsl:apply-templates select="*|@*|text()"/> </xsl:copy> </xsl:template> <xsl:template match="@*"> <xsl:attribute name="{name()}"> <xsl:value-of select="translate(.,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> </xsl:attribute> </xsl:template> <xsl:template match="text()"> <xsl:value-of select="translate(.,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> </xsl:template> </xsl:stylesheet>Rappelons que XSL-FO s'occupe presque exclusivement du formatage pour impression. On trouvera sur notre page tutxmlfo.htm une introduction à XSL-FO en vue de production de documents PDF.
5. Exemples réels de documents, grammaires et transformations
retour en haut de document
Comme premier exemple réel, on pourra consulter le fichier actes_fichiers_xml.htm. La partie 2 de ce fichier montre comment une collectivité peut accéder à la classification des actes pour une sous-préfecture, puis lui transmettre un arrêté individuel d'urbanisme à savoir un permis de construire, obtenir un accusé de réception etc.
Comme suite logique, on pourra consulter avec profit le répertoire des schémas XML de l'administration (copie locale ici) sur le site de l'ADAE qui était l'Agence pour le Développement de l'Administration en ligne et dont le le programme gouvernemental était nommé "le programme ADELE".
On pourra également consulter le site des schémas Xml de service-public.fr et la DTD ÉRÉLÉ du site l'informatique au ministère de l'équipement via le CCI (Cadre Commun d'Interopérabilité), cadre inclus dans le RGI (Référentiel Général d'Interopérabilité).
Un autre exemple est celui d'une page nommée cours.fo pour support de cours avec inclusion de marges, de solutions suivant le paramétrage ; les instructions XML générales sont en bleu, les instructions XSL en vert et les instructions XSL-FO en noir :
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:import href="ligneFo.xsl"/> <xsl:import href="commentFo.xsl"/> <xsl:template match="PAGE"> <xsl:param name="numPage"/> <xsl:param name="soPage"/> <!-- pour ne pas générer les pages de solution <xsl:if test="not(starts-with(@NOM,'sol'))">--> <!-- pour ne générer que les pages à vérifier <xsl:if test="@AVERIFIER='o'">--> <fo:block font-size="12pt" line-height="15pt" text-align="start" border-left-style="solid" border-right-style="solid" border-before-style="solid" border-after-style="solid"> <xsl:if test="$soPage = 1"> <xsl:attribute name="break-before">page</xsl:attribute> </xsl:if> <xsl:attribute name="id"><xsl:value-of select="@NOM"/></xsl:attribute> <fo:block keep-with-next="always" text-align="center" font-size="20pt" line-height="30pt" space-after.optimum="20pt"> <xsl:value-of select="Titre[not(@xml:lang) or @xml:lang = $lang]"/> </fo:block> <xsl:apply-templates select="LIGN"/> <xsl:call-template name="infoPage"> <xsl:with-param name="numPage" select="$numPage"/> </xsl:call-template> <fo:block white-space-collapse="false" font-size="12pt" line-height="15pt" text-align="start" space-after.optimum="40pt"> <xsl:apply-templates select="COMMENT"/> </fo:block> </fo:block> <!--/xsl:if--> <xsl:apply-templates select="id(SUCC)"> <xsl:with-param name="numPage" select="$numPage + 1"/> <xsl:with-param name="soPage"> <xsl:choose> <xsl:when test="starts-with(SUCC,'sommair')">1</xsl:when> <xsl:when test="SUCC='user1'">1</xsl:when> <xsl:when test="SUCC='use7'">1</xsl:when> <xsl:when test="SUCC='use11'">1</xsl:when> <xsl:when test="SUCC='use12'">1</xsl:when> <xsl:when test="SUCC='relr1'">1</xsl:when> <xsl:when test="SUCC='use13'">1</xsl:when> <xsl:when test="SUCC='use14'">1</xsl:when> <xsl:when test="SUCC='relr3'">1</xsl:when> <xsl:when test="SUCC='use18'">1</xsl:when> <xsl:when test="SUCC='relr4'">1</xsl:when> <xsl:when test="SUCC='use19'">1</xsl:when> <xsl:when test="SUCC='relr5'">1</xsl:when> <xsl:when test="SUCC='comr1'">1</xsl:when> <xsl:when test="SUCC='comr2'">1</xsl:when> <xsl:when test="SUCC='docr'">1</xsl:when> <xsl:when test="SUCC='atuse1'">1</xsl:when> <xsl:when test="SUCC='packr2'">1</xsl:when> <xsl:when test="SUCC='pack6'">1</xsl:when> <xsl:when test="SUCC='packr3'">1</xsl:when> <xsl:when test="SUCC='pack7'">1</xsl:when> <xsl:when test="SUCC='compr2'">1</xsl:when> <xsl:when test="SUCC='classer1'">1</xsl:when> <xsl:when test="SUCC='act8'">1</xsl:when> <xsl:when test="SUCC='act10'">1</xsl:when> <xsl:when test="SUCC='actir5'">1</xsl:when> <xsl:when test="SUCC='actir6'">1</xsl:when> <xsl:when test="SUCC='act15'">1</xsl:when> <xsl:when test="SUCC='jaco'">1</xsl:when> <xsl:otherwise> <xsl:value-of select="($soPage +1) mod $nbSlide"/> </xsl:otherwise> </xsl:choose> </xsl:with-param> </xsl:apply-templates> </xsl:template> <xsl:template name="infoPage"> <xsl:param name="numPage"/> <fo:block keep-with-next="always" text-align="center" font-size="10pt" line-height="12pt" border-before-style="solid" border-after-style="solid"> <fo:table background-color="cyan" table-layout="fixed"> <fo:table-column column-width="32mm"/> <fo:table-column column-width="32mm"/> <fo:table-column column-width="32mm"/> <fo:table-column column-width="32mm"/> <fo:table-column column-width="32mm"/> <fo:table-body> <fo:table-row> <fo:table-cell> <fo:block> <xsl:value-of select="/COURS/@TITREC"/> : <xsl:value-of select="@NOM"/> </fo:block> </fo:table-cell> <fo:table-cell> <fo:block> <xsl:value-of select="/COURS/@VERSION"/> </fo:block> </fo:table-cell> <fo:table-cell> <fo:block> <xsl:value-of select="/COURS/@AUTEUR"/> </fo:block> </fo:table-cell> <fo:table-cell> <fo:block> <xsl:choose> <xsl:when test="$entreprise='ltm' and $entreprise2 != ''"> LTM</xsl:when> <xsl:otherwise> <xsl:value-of select="/COURS/@MEL"/> </xsl:otherwise> </xsl:choose> </fo:block> </fo:table-cell> <fo:table-cell> <fo:block> <xsl:value-of select="$numPage "/> / <xsl:value-of select="count(/COURS/PAGE) - 1"/> </fo:block> </fo:table-cell> </fo:table-row> </fo:table-body> </fo:table> </fo:block> </xsl:template> </xsl:stylesheet>retour à la table des matières principales