jeudi 7 mai 2015

XSL:FO : gestion multi pages

XSL:FO permet de décrire les mises en forme de documents XML quel que soit le support (écran, papier, ...).

Par exemple, il est possible de générer ainsi un document PDF à partir de données XML.

Une des difficultés est de gérer correctement un document multi - pages.

Imaginez que vous deviez mettre en forme des lignes d'une facture et que vous souhaitiez faire un saut de page toutes les 15 lignes.

Voici un extrait d'un document XSL:FO type :

<fo:table table-layout="fixed" border-spacing="3px 3px">
...
<fo:table-body background-color="white" border-color="black"

border-width="1px" border-style="solid">
<xsl:for-each select="Ligne">

<fo:table-row space-before.optimum="0pt">
<!-- gestion des sauts de page -->
<xsl:if test="position() mod 15 = 0">
<xsl:attribute name="break-after">page</xsl:attribute>
</xsl:if>

<fo:table-cell padding="3px">
<fo:block text-align-last="center">
<xsl:value-of select="ref" />
</fo:block>
</fo:table-cell>
<fo:table-cell padding="3px">
<fo:block text-align-last="center">
<xsl:value-of select="designation" />
</fo:block>
</fo:table-cell>
<fo:table-cell padding="3px">
<fo:block text-align-last="center">
<xsl:value-of select="qte" />
</fo:block>
</fo:table-cell>
<fo:table-cell padding="3px">
<fo:block text-align-last="right">
<xsl:value-of select="format-number(pu_ht, '### ###.00')" />
</fo:block>
</fo:table-cell>
<fo:table-cell padding="3px">
<fo:block text-align-last="right">
<xsl:if test="remise > 0">
<xsl:value-of select="format-number(remise, '### ###.00')" />
</xsl:if>
<xsl:if test="contains(remise, '%')">
<xsl:value-of select="remise" />
</xsl:if>
</fo:block>
</fo:table-cell>
<fo:table-cell padding="3px">
<fo:block text-align-last="right">
<xsl:value-of select="format-number(total_ht, '### ###.00')" />
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
...
            </fo:table>

Un extrait des données XML associées :

<Lignes>
...
<Ligne>
<ref>XXXX_105</ref>
<designation>Carte mère</designation>
<qte>1</qte>
<pu_ht>160</pu_ht>
<remise>34.55</remise>
<total_ht>125.45</total_ht>
</Ligne>
<Ligne>
<ref>FORT1</ref>
<designation>Forfait maintenance</designation>
<qte>1</qte>
<pu_ht>60</pu_ht>
<remise>15%</remise>
<total_ht>51</total_ht>
</Ligne>
<Ligne>
<ref>FORT2</ref>
<designation>Forfait maintenance 2</designation>
<qte>1</qte>
<pu_ht>70</pu_ht>
<remise></remise>
<total_ht>60</total_ht>
</Ligne>
<Ligne>
<ref>FORT3</ref>
<designation>Forfait maintenance 3</designation>
<qte>1</qte>
<pu_ht>80</pu_ht>
<remise></remise>
<total_ht>60</total_ht>
</Ligne>
<Ligne>
<ref>FORT4</ref>
<designation>Forfait maintenance 2</designation>
<qte>1</qte>
<pu_ht>70</pu_ht>
<remise></remise>
<total_ht>60</total_ht>
</Ligne>
<Ligne>
<ref>FORT5</ref>
<designation>Forfait maintenance 3</designation>
<qte>1</qte>
<pu_ht>80</pu_ht>
<remise></remise>
<total_ht>60</total_ht>
</Ligne>
...
</Lignes>

Simple non ?

Oui, mais vous devez prendre une précaution importante sinon votre gestion multi - pages ne fonctionnera pas.

Votre <FO:TABLE> ne doit pas être dans un <FO:BLOCK-CONTAINER> qui est positionné en valeur absolue (propriété : position='absolute') -  d'après les spécifications XSL.

Si cela est le cas, votre gestion multi - pages sera ignorée.

Pour remédier à ce problème, la meilleure chose à faire est de supprimer le <FO:BLOCK-CONTAINER>.

Vous pouvez aussi modifier les propriétés de <FO:REGION-BODY> en y reportant les valeurs des propriétés précédemment initialisées dans le <FO:BLOCK-CONTAINER> (ex : "margin-top" de <FO:REGION-BODY> = valeur propriété "top" de <FO:BLOCK-CONTAINER).

Aucun commentaire:

Enregistrer un commentaire