Articles avec #xslt tag

Publié le 29 Août 2012

J'utilise XSLT pour générer de la documentation. Dans le cas qui nous intéresse ici, il s'agit d'afficher un tableau avec différentes informations. La construction du tableau s'effectue par l'ajout de ligne à travers une boucle for-each:

<xsl:template name="article-rows" match="ARTICLES">
 <xsl:foreach select ="ARTICLE">
  <fo:table-row>
    <fo:table-cell>
     <fo:block>article n° : <xsl:value-of select ="position()"/></fo:block>
   </fo:table:cell>
  </fo:table-row>
 </xsl:foreach>
</xsl:template>

Maintenant je dois traiter la première ligne d'une manière différente. Je dois donc savoir s'il s'agit de la première iteration de la boucle for-each. Hors en XSLT les variable sont toutes final, ce qui signifie qu'on ne peut pas modifier leur valeur après initialisation.

Par conséquence il est impossible d'utiliser une variable 'i' qu'on incrémente à chaque itération. (pas modifiable, je vous dis!)

Heureusement il existe la fonction position() qui retourne exactement le nombre d'iteration effectuées dans une boucle.

Ainsi il est facile de tester s'il s'agit de la première itération:

 

<xsl:template name="article-rows" match="ARTICLES">
 <xsl:foreach select ="ARTICLE">
  <fo:table-row>
    <fo:table-cell>
     <fo:block>
      <xsl:if test="position()=1">premier article</xsl:if>
      <xsl:if test="not(position()=1)">article n° : <xsl:value-of select ="position()"/></xsl:if>
    </fo:block>
   </fo:table:cell>
  </fo:table-row>
 </xsl:foreach>
</xsl:template>

De même pour la dernière ligne on peut ajouter un if pour modifier la dernière ligne. Mais il faut utiliser la fonction last() pour savoir s'il s'agit de la dernière iteration (Et oui on ne connaît forcément le nombre d'itération à l'avance).

<xsl:if test="position()=last()">...</xsl:if>

Voir les commentaires

Rédigé par Bliz

Publié dans #XSLT

Repost 0

Publié le 25 Mai 2012

Pour étendre une cellule sur plusieurs ligne on peut utiliser rowspan:

rowspan sur 3 lignes ligne 1
ligne 2
ligne 3

xsl-fo est souvent utilisé pour générer de la documentation imprimables (pdf) et bien sûr il est possible d'effectuer le même effet de rowspan qu'en html:

<fo:block>
 <fo:table>
  <fo:table-column/>
  <fo:table-column/>
  <fo:table-body>
   <fo:table-row>
    <fo:table-cell number-rows-spanned="3">
     <fo:block>rowspan sur 3 lignes</fo:block>
    </fo:table-cell>
    <fo:table-cell>
     <fo:block>ligne 1</fo:block>
    </fo:table-cell>
   </fo:table-row>
   <fo:table-row>
    <fo:table-cell>
     <fo:block>ligne 2</fo:block>
    </fo:table-cell>
   </fo:table-row> 
   <fo:table-row>
    <fo:table-cell>
     <fo:block>ligne 3</fo:block>
    </fo:table-cell>
   </fo:table-row>  
  </fo:table-body>
 </fo:table>
</fo:block>

Bien sûr c'est beaucoup plus "wordy" qu'en HTML mais le principe reste le même on déclare le rowspan sur la première ligne.
Puis les lignes suivantes ont une cellule de moins. 

Voir les commentaires

Rédigé par Bliz

Publié dans #XSLT

Repost 0

Publié le 8 Mars 2010

Avec XSLT, l'objet Date permet de manipuler les dates et donc de récupérer la date courante et d'en extraire les différents éléments pour l'afficher selon différent formats.

Par exemple voici la méthode qui permet d'afficher la date courante au format YYYY-MM-DD hh:mm:ss

<!-- retourne la date courante au format YYYY-MM-DD hh:mm:ss -->
<xsl:template name="CurrentDateTime">
   <!-- recuperation de la date courante dans un objet date -->
   <xsl:variable name="date" select="date:new()"/>
   <!-- Extraction des donnees necessaires a l'affichage de la date -->
   <xsl:variable name="year" select="date:getYear()+1900" />
   <xsl:variable name="month" select="date:getMonth()+1" />
   <xsl:variable name="day" select="date:getDate()" />
   <xsl:variable name="hrs" select="date:getHours()" />
   <xsl:variable name="min" select="date:getMinutes()" />
   <xsl:variable name="sec" select="date:getSeconds()" />
   <!-- formatage et afficage de la date -->
   <xsl:value-of select="$year" />
   <xsl:text>-</xsl:text>   
   <xsl:value-of select="format-number($month,'00')"/>
   <xsl:text>-</xsl:text>
   <xsl:value-of select="format-number($day,'00')"/>
   <xsl:text> </xsl:text>
   <xsl:value-of select="format-number($hrs,'00')"/>
   <xsl:text>:</xsl:text>
   <xsl:value-of select="format-number($min,'00')"/>
   <xsl:text>:</xsl:text>
   <xsl:value-of select="format-number($sec,'00')"/>
</xsl:template>

La fonction format-number($number, '00') permet d'afficher un nombre sur 2 caractères (en complétant avec un 0) même quand ce nombre est inférieur à 10.
Par exemple 2 s'affichera sous la forme 02.

Pour récupérer la date courante il suffit d'appeler le template CurrentDateTime.
Ainsi pour placer le résultat dans une variable:

<xsl:variable name="now">
   <xsl:call-template name="CurrentDateTime" />
</xsl:variable>

On peut utiliser d'autres formats par exemple si on veut utiliser un timestamp unix on utilisera le template suivant de la même manière que précédemment:

<!-- retourne la date courante sous la forme d'un timestamp Unix -->
<xsl:template name="CurrentTimestamp">
   <!-- recuperation de la date courante dans un objet date -->
   <xsl:variable name="date" select="date:new()"/>
   <!-- Extraction des donnees necessaires a l'affichage du timestamp -->
   <xsl:variable name="time" select="date:getTime() div 1000" />
   <!-- getTime() retourne le nombre de millisecondes depuis le 1er janvier 1970 -->
   <!-- donc pour avoir le nombre de secondes on divise par 1000 -->


   <!-- formatage et afficage de la date -->
   <xsl:value-of select="$time" />  
</xsl:template>

Voir les commentaires

Rédigé par Bliz

Publié dans #XSLT

Repost 0

Publié le 19 Février 2010

L'article du jour est une petite introduction à XSLT.

XSLT est un outils de transformation de document. On l'utilise surtout (en tout cas dans la plupart des cas que j'ai rencontrés) pour faire des transformations à l'intérieur d'un document XML, mais il peut aussi servir à générer d'autre types de document.

Ici, en guise d'introduction à XSLT nous allons transformer un document XML en un document texte tout simple.
Et cerise sur le gâteau, notre document texte sera au format CSV (c'est à dire qu'il utilise des "," ou ";" comme séparateur de  champs) et donc on pourra l'ouvrir directement dans Excel.
Donc tout d'abord voilà le fichier XML source que nous allons transformer:

Contenu du fichier films.xml :
<?xml version="1.0" encoding="utf-8"?>
<ListeFilm>
 <Film id="1">
  <Titre>Invictus</Titre>
  <Realisateur>Clint Eastwood</Realisateur>
 </Film>
 <Film id="2">
  <Titre>Sumo</Titre>
  <Realisateur>Sharon Maymon</Realisateur>
 </Film>
 <Film id="3">
  <Titre>Gainsbourg</Titre>
  <Realisateur>Joann Sfar</Realisateur>
 </Film>
 <Film id="4">
  <Titre>Lebanon</Titre>
  <Realisateur>Samuel Maoz</Realisateur>
 </Film>
 <Film id="5">
  <Titre>Planet 51</Titre>
  <Realisateur>Jorge Blanco</Realisateur>
 </Film>
</ListeFilm>


A partir de ce fichier, nous allons générer un fichier texte avec une ligne par film au format suivant:

ID;Titre;Réalisateur

Pour ce faire nous avon besoin de définir quelques règles à appliquer pour effectuer cette transformation. Ces règles doivent être définies dans un fichier .xsl. Ce fichier n'est rien d'autre qu'un document XML. Dans notre cas il se présente de la manière suivante:

Contenu du fichier films.xsl:
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:date="http://xml.apache.org/xalan/java/java.util.Date"
    xmlns:java_lang="http://xml.apache.org/xalan/java/java.lang"
    exclude-result-prefixes="date java_lang">

 <xsl:output method="text"/>
 
 <xsl:variable name="newLine" select="translate('&#xa;','','')"/> 
 
 <!-- ListeFilm transformation -->
 <xsl:template match="ListeFilm">
 
<!-- Affichage de l'entête (nom des champs) -->
  <xsl:text>ID;Titre;Realisateur</xsl:text>
  <xsl:value-of select="$newLine" />

  <xsl:apply-templates select="*" />
 </xsl:template>
 
 <!-- Film transformation  -->
 <xsl:template match="Film">
   <!-- Recuperation des informations du fichier XML -->
   <xsl:variable name="identifiant" select="@id" />
   <xsl:variable name="titre" select="./Titre" />
   <xsl:variable name="realisateur" select="./Realisateur"/>  
   <!-- Generation du contenu -->
   <xsl:value-of select="$identifiant" />
   <xsl:text>;</xsl:text>
   <xsl:value-of select="$titre" />
   <xsl:text>;</xsl:text>
   <xsl:value-of select="$realisateur" />
   <xsl:value-of select="$newLine" />
 </xsl:template>

</xsl:stylesheet>


Voilà maintenant nous avons notre fichier source et les règles à appliquer pour effectuer la transformation. Nous sommes prêts à passer à l'action. Et pour ce faire nous allons utiliser "ant" qui est plus ou moins un équivalent de "make" et qui est très utilisé pour compiler des applications (java notamment).

Nous allons l'utiliser ici pour effectuer une transformation XSLT.

"Ant" se base sur un fichier xml, généralement appelé "build.xml", dans lequel on définit les actions (ou tâches) à effectuer.
Ici nous allons réaliser une seule tache : la transformation XSLT. Donc notre fichier build.xml doit ressembler à ça:

<?xml version="1.0" encoding="utf-8"?>
<project name="Films-XSLT" default="run">
 <target name="run">
    <!-- transformation de films.xml en films.txt -->
    <!-- en appliquant les règles xsl définies dans films.xsl -->
    <xslt style="./films.xsl" in="./films.xml" out="films.txt" />
  </target>
</project>


Pour effectuer la transformation, on lance la commande (dans cygwin par exemple):

ant

tout simplement !

Et voilà le résultat:

ID;Titre;Realisateur
1;Invictus;Clint Eastwood
2;Sumo;Sharon Maymon
3;Gainsbourg;Joann Sfar
4;Lebanon;Samuel Maoz
5;Planet 51;Jorge Blanco

Et comme je l'ai dit plus haut, on peut ouvrir ce fichier avec Excel. Il suffit de le renommer en "films.csv" et le tour est joué!


Voir les commentaires

Rédigé par Bliz

Publié dans #XSLT

Repost 0