<?xml version="1.0" encoding="utf-8"?>
<document>
   <titre>Introduction à XSL-FO (Suite)</titre>
   <contenu>
<h2><abbr title="XSL Formatting Objects">XSL-FO</abbr> via <abbr title="XSL Transformation">XSLT</abbr></h2>

<p class="abstract">
   Cet article s’inscrit dans la continuïté de l’<a href="/articles/Introduction_XSL-FO">Introduction à XSL-FO</a> en prenant
   un exemple concret de transformation d’un contenu XML existant pour en faire un joli PDF (du moins XSL-FO).
</p>

<h3>Le But</h3>

<p>
   Étant un afficionados de la salle de concert <a href="http://fr.wikipedia.org/wiki/Bikini_Test">Bikini Test</a>, je
   souhaiterais avoir une version papier de l’<a href="http://www.bikinitest.ch/newsite/agenda.php">agenda (du mois)</a>
   pouvant être imprimée pour faire un peu de pub à gauche
   à droite. L’impression CSS devrait suffire mais loin de moi l’idée de lacher <a
   href="http://web.archive.org/web/20050317020459/http://www.xml.com/pub/a/2005/01/19/print.html" hreflang="en">le troll</a>.
</p>

<p>
   Avant de commencer, veuillez vous munir des outils nécessaires.
</p>

<h4>Les outils</h4>

<p>
    Pour les (heureux) utilisateurs d’une distribution UN*X, je ne peux que vous conseiller d’utiliser
    <a href="http://libxml.org/" hreflang="en">xsltproc</a> conjointement à
    <a href="http://xmlgraphics.apache.org/fop/" hreflang="en">FOP</a>. Quant aux windowsiens,
    <a href="http://www.xmlcooktop.com/">Cooktop</a> (qui utilise Internet Explorer par derrière)
    est pas si mal.
</p>

<h3>Dégrossissage</h3>

<p>
   Avant d’appliquer une quelconque mise en forme, une première feuille de style pour récupèrer l’information utile.
   Un conseil : ayez sous les yeux le code source de l’agenda.
</p>

<h4><a href="simple.xsl">Simple.xsl</a></h4>

<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"&gt;
    
    <span style="color:#090;">&lt;!-- Le mode de sortie (ici du texte) --&gt;</span>
    &lt;xsl:output method="text" /&gt;

    &lt;xsl:template match="/"&gt;
        <span style="color:#090;">&lt;!-- Récupération de la valeur de l’élément title (dans le head) --&gt;</span>
        &lt;xsl:value-of select="//xhtml:title" /&gt;
        
        <span style="color:#090;">&lt;!-- Pour chaques blocs : div.prog_entry --&gt;</span>
        &lt;xsl:for-each select="//xhtml:div[@class = 'prog_entry']"&gt;
            &lt;xsl:text&gt;
 - &lt;/xsl:text&gt;
            <span style="color:#090;">&lt;!-- affichage du contenu textuel de l'élément : dd.title --&gt;</span>
            &lt;xsl:value-of select="xhtml:dl/xhtml:dd[@class = 'title']" /&gt;
        &lt;/xsl:for-each&gt;
    &lt;/xsl:template&gt;

&lt;/xsl:stylesheet&gt;</pre>

<p>
   La transformation : <code>xsltproc simple.xsl http://www.bikinitest.ch/newsite/agenda.php</code> <br />
   donnera le résultat suivant (pour le mois de mai 2006)
</p>

<pre>Bikini Test - Agenda
 - House Of Fix (UK)
 - Cult Of Luna (SWE) (Unique Date CH)
 - The Poets Of Rhythm (D)(Quannum/Ninja Tune) Live
 - Winterthur Rocks!
 - Beautés Vulgaires (F)
 - Masterclass de la BAF'!</pre>

<h4>XPath</h4>

<p>
   Pour introduire rapidement les chemins XPath (ceux utilisés dans les <code>select</code> et <code>match</code>),
   un document est un arbre où chaque nœud est une balise. Typiquement pour un document XHTML.
</p>

<pre>
        html
      /      \
 body         head
  /   \        \
 p   div     title
      /   \
    ul     p
   /  \
  li  li
</pre>

<p>
    Un nœud est identifié par son chemin : le titre <code>/html/head/title</code> ou <code>//title</code> toutes les balises <code>title</code>.
    Ensuite les attributs d’un nœud sont accessibles via le <code>@</code>, par exemple <code>a/@href</code> pour obtenir où pointe un
    lien hypertexte.
</p>

<h5>Les conditions</h5>

<p>
    Dans l’exemple ci-dessus, les différents <code>dd</code> sont différenciés selon leur classe. Avec les parenthèses carrées <code>[ ]</code>,
    une condition peut être appliquée à un nœud : <code>//dd[@class = 'foobar']</code> va séléctionner tous les <code>dd</code> de la
    classe <code>foobar</code>. Ce que l’on ferait avec <code>dd.foobar</code> en CSS.
</p>

<h3>Récupérer tout le contenu</h3>

<p>
    Ce qui va nous intéresser pour notre document imprimé sont les blocs représentant la soirée ainsi qu'éventuellement le titre du contenu
    qui indique quel mois est affiché.
</p>

<p>
    Première étape se placer au niveau des entrées du programme, dans le contenu : <code>//div[@id = 'contenu']</code> et
    afficher chaque <code>div[@class = 'prog_entry']</code> en fonction de ce qu’il contient (<code>dd[@class = 'title']</code>, ...).
</p>

<pre>
...
&lt;xsl:apply-templates select="//xhtml:div[@id = 'contenu']" /&gt;
...

&lt;xsl:template match="xhtml:div[@id = 'contenu']"&gt;
   &lt;xsl:apply-templates select="xhtml:div" /&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match="xhtml:div[@class = 'prog_entry']"&gt;
   &lt;xsl:apply-templates /&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match="xhtml:dd[@class = 'title']"&gt;
   &lt;xsl:text&gt;titre : &lt;/xsl:text&gt;
   &lt;xsl:apply-templates /&gt;
&lt;/xsl:template&gt;

<span style="color:#090;">&lt;!-- Ne rien faire des divs non-sélectionnés précédemment --&gt;</span>
&lt;xsl:template match="xhtml:div" /&gt;
</pre>

   </contenu>
   <zone>
   </zone>
</document>                  		