J'utilise XSL FO pour générer un fichier PDF contenant un tableau avec des informations. Une de ces colonnes est une colonne "Description". Voici un exemple de chaîne que je remplis avec l'un de ces champs Description:
This is an example Description.<br/>List item 1<br/>List item 2<br/>List item 3<br/>List item 4
À l'intérieur de la cellule de tableau qui correspond à cette description, j'aimerais que la sortie s'affiche comme telle:
This is an example Description.
List item 1
List item 2
List item 3
List item 4
En cherchant ailleurs, j'ai appris que vous pouvez faire des sauts de ligne en XSL FO en utilisant un <fo:block></fo:block>
dans un autre élément <fo:block>
. Par conséquent, même avant d'analyser le code XML avec ma feuille de style XSL, je remplace toutes les occurrences de <br/>
par <fo:block/>
, de sorte que la valeur littérale de la chaîne ressemble maintenant à ceci:
This is an example Description.<fo:block/>List item 1<fo:block/>List item 2<fo:block/>List item 3<fo:block/>List item 4
Le problème se pose lorsque la chaîne de description que j'utilise est obtenue à l'aide de <xsl:value-of>
, par exemple:
<fo:block>
<xsl:value-of select="descriptionStr"/>
</fo:block>
Dans ce cas, la valeur qui est générée dans mon document PDF est la valeur littérale. Elle ressemble donc exactement à l'exemple précédent avec tous les littéraux <fo:block/>
. J'ai essayé manuellement de coder en dur le <fo:block/>
au milieu d'une autre chaîne et il s'affiche correctement. Par exemple. si j'écris dans ma feuille de style:
<fo:block>Te<fo:block/>st</fo:block>
Il s'affichera correctement comme suit:
Te
st
Mais cela ne semble pas se produire lorsque le <fo:block/>
est dans la valeur d'une instruction <xsl:value-of select=""/>
. J'ai essayé de rechercher ceci sur SO ainsi que sur Google, etc., sans succès. Tout conseil ou aide sera grandement apprécié. Je vous remercie!
Vous ne devriez pas utiliser l'instruction xsl:value-of
mais plutôt xsl:apply-templates
: pour une règle intégrée, le nœud texte ne doit afficher que la valeur de chaîne. Pour un élément br
vide, vous pouvez déclarer une règle correspondant à descriptionStr/br
ou descriptionStr//br
(selon votre entrée) afin de la transformer en fo:block
vide.
Vous pouvez également remplacer <br/>
par 

et ajouter un attribut linefeed-treatment="preserve"
à votre <fo:block>
.
Quelque chose comme:
<fo:block linefeed-treatment="preserve">This is an example Description.
List item 1
List item 2
List item 3
List item 4</fo:block>
Modifier
Certains utilisateurs peuvent avoir besoin d'utiliser \n
au lieu de 

en fonction de la manière dont ils créent le XML. Voir Conserver le & # xA; xml marshalling pour plus de détails.
Cela m'a aidé et devrait être la solution la plus simple (travailler avec Apache FOP 1.1):
Pourquoi ne pas remplacer votre <br/>
par un caractère Unicode appelé séparateur line.
<xsl:template match="br">
<xsl:value-of select="'
'"/>
</xsl:template>
Le code suivant a fonctionné:
<fo:block white-space-collapse="false"
white-space-treatment="preserve"
font-size="0pt" line-height="15px">.</fo:block>
Cela fait croire au processeur xsl que ce bloc contient une ligne de texte, qui a en fait une taille de police de 0pt. Vous pouvez personnaliser la hauteur de ligne en fournissant votre propre valeur.
Générer des chaînes contenant un balisage XML échappé est rarement la bonne réponse, mais si c'est avec cela que vous devez travailler, utilisez une entrée comme celle-ci:
<Description><![CDATA[This is an example Description.<br/>List item 1<br/>List item 2<br/>List item 3<br/>List item 4]]></Description>
si vous utilisez XSLT 2.0, vous pouvez utiliser xsl:analyze-string
pour obtenir le fo:block
vide que vous vouliez à l'origine:
<xsl:template match="Description">
<fo:block>
<xsl:analyze-string select="." regex="<br/>">
<xsl:matching-substring>
<fo:block />
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</fo:block>
</xsl:template>
mais si vous utilisez XSLT 2.0, vous pouvez utiliser de manière plus précise linefeed-treatment="preserve"
conformément à @ Daniel Haley et utiliser replace()
pour insérer les sauts de ligne:
<xsl:template match="Description">
<fo:block linefeed-treatment="preserve">
<xsl:value-of select="replace(., '<br/>', '
')" />
</fo:block>
</xsl:template>
Si vous utilisez XSLT 1.0, vous pouvez suivre votre chemin dans la chaîne:
<xsl:template match="Description">
<fo:block linefeed-treatment="preserve">
<xsl:call-template name="replace-br" />
</fo:block>
</xsl:template>
<xsl:template name="replace-br">
<xsl:param name="text" select="." />
<xsl:choose>
<xsl:when test="not(contains($text, '<br/>'))">
<xsl:value-of select="$text" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($text, '<br/>')"/>
<xsl:text>
</xsl:text> <!-- or <fo:block /> -->
<xsl:call-template name="replace-br">
<xsl:with-param name="text" select="substring-after($text, '<br/>')"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Essaye ça:
<fo:block><fo:inline color="transparent">x</fo:inline></fo:block>
Ce code ajoute un bloc contenant du texte transparent, le faisant ressembler à une nouvelle ligne.
Essayez d’utiliser linefeed-treatment = "preserve" et\n au lieu de <br>
pour une nouvelle ligne.
<fo:block linefeed-treatment="preserve" >
<xsl:value-of select="Description" />
</fo:block>
J'utilise généralement un bloc vide d'une hauteur modifiable si j'ai besoin de plus ou moins d'espace:
<fo:block padding-top="5mm" />
Je sais que ce n’est pas la meilleure solution, mais c’est fonctionnel.
J'ai eu un bloc de texte qui ressemble à ceci
<fo:table-cell display-align="right">
<fo:block font-size="40pt" text-align="right">
<xsl:text> Text 1 </xsl:text>
<fo:block> </fo:block>
<xsl:text> Text2 </xsl:text>
<fo:block> </fo:block>
<xsl:text> Text 3</xsl:text>
</fo:block>
NB: notez le vide
Pour XSL-FO, il prend en charge