<?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:#060;">&lt;!-- Ne rien faire des divs non-sélectionnés précédemment --&gt;</span>
&lt;xsl:template match="xhtml:div" /&gt;
</pre>

<p>
   À partir de là et avec l’<a href="/articles/Introduction_XSL-FO">article précédant</a> il me semble que les bases
   sont posées pour obtenir un résultat sympa.
</p>

<h3>Le résultat final</h3>

<p>
   Avant d’aller directement au but, j’aimerais relever un élément intéressant : les liens. Il est possible, dans un document
   PDF, d’avoir des liens externes (aussi bien qu’interne d’ailleurs) et les liens des soirées sur les groupes. Mais une fois le
   document imprimé, les liens ne sont plus utiles, il en faut une version textuelle. Pour ce faire, une note de bas de page.
</p>

<pre>
&lt;xsl:template match="xhtml:a">
    &lt;fo:basic-link color="#333" external-destination="{@href}"&gt;
        &lt;xsl:apply-templates /&gt;
    &lt;/fo:basic-link&gt;
    &lt;fo:footnote&gt;
        &lt;fo:inline font-size="60%" vertical-align="super"&gt;
            <span style="color:#090;">&lt;!-- Comptage des liens externes précédants --&gt;</span>
            &lt;xsl:value-of select="count(preceding::xhtml:a[starts-with(@href,
                'http://')]) + 1" /&gt;
        &lt;/fo:inline&gt;
        &lt;fo:footnote-body&gt;
        &lt;fo:block font-size="8pt" color="#000" font-weight="normal"&gt;
            &lt;xsl:value-of select="count(preceding::xhtml:a[starts-with(@href,
                'http://')]) + 1" /&gt;
            &lt;xsl:text&gt;) &lt;/xsl:text&gt;
            &lt;xsl:value-of select="@href" /&gt;
        &lt;/fo:block&gt;
    &lt;/fo:footnote-body&gt;
    &lt;/fo:footnote&gt;
&lt;/xsl:template&gt;
</pre>

<p>Télécharger la feuille de transformation : <a href="template.xsl">template.xsl</a> et <a href="agenda-200605.pdf">le résultat</a> (pour le mois de mai).

   </contenu>
   <zone>
      <h3>Liens</h3>
      <ul>
         <li><a href="http://zvon.org/o_html/group_xsl.html" hreflang="en">Zvon: XSL Programmers</li>
         <li><a href="http://fr.wikipedia.org/wiki/XPath" hreflang="fr">Wikipédia: XPath</a></li>
      </ul>
      <dl>
         <dt>Auteur</dt>
         <dd>Yoan Blanc</dd>
      </dl>
   </zone>
</document>                              		