2010-12-03 47 views
2

Je rencontre un problème lorsque je publie mes modspecs en pdf (XSL-FO). Mes tables ont des problèmes, où le contenu d'une cellule débordera de sa colonne dans la suivante. Comment puis-je forcer une pause sur le texte afin qu'une nouvelle ligne soit créée à la place?XSL-FO: Force Wrap sur les entrées de table

Je ne peux pas insérer manuellement des caractères à espace nul, car les entrées de table sont entrées par programme. Je suis à la recherche d'une solution simple que je peux simplement ajouter à docbook_pdf.xsl (soit en tant que xsl: param ou xsl: attribute)

EDIT: est ici où je suis actuellement:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
<xsl:import href="urn:docbkx:stylesheet"/> 
...(the beginning of my stylesheet for pdf generation, e.g. header and footer content stuff) 
<xsl:template match="text()"> 
    <xsl:call-template name="intersperse-with-zero-spaces"> 
     <xsl:with-param name="str" select="."/> 
    </xsl:call-template> 
</xsl:template> 
<xsl:template name="intersperse-with-zero-spaces"> 
    <xsl:param name="str"/> 
    <xsl:variable name="spacechars"> 
     &#x9;&#xA; 
     &#x2000;&#x2001;&#x2002;&#x2003;&#x2004;&#x2005; 
     &#x2006;&#x2007;&#x2008;&#x2009;&#x200A;&#x200B; 
    </xsl:variable> 

    <xsl:if test="string-length($str) &gt; 0"> 
     <xsl:variable name="c1" select="substring($str, 1, 1)"/> 
     <xsl:variable name="c2" select="substring($str, 2, 1)"/> 

     <xsl:value-of select="$c1"/> 
     <xsl:if test="$c2 != '' and 
      not(contains($spacechars, $c1) or 
      contains($spacechars, $c2))"> 
      <xsl:text>&#x200B;</xsl:text> 
     </xsl:if> 

     <xsl:call-template name="intersperse-with-zero-spaces"> 
      <xsl:with-param name="str" select="substring($str, 2)"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

Avec cela, les mots longs sont rompus avec succès dans les cellules du tableau! Malheureusement, l'effet secondaire est que le texte normal ailleurs (comme dans une sous-sextion X) rompt maintenant les mots de sorte qu'ils apparaissent sur des lignes séparées. Existe-t-il un moyen d'isoler le processus ci-dessus à seulement des tables?

+0

Cela ressemble plus à une question de vocabulaire XSL-FO. J'ai revérifié comme tel. Si vous pensez être une question XSLT, veuillez fournir un échantillon d'entrée et la sortie désirée. –

+0

@Alejandro: Oui c'est techniquement un problème XSL-FO (puisque le problème ne se termine pas en html). Je suppose que j'espère un moyen d'ajouter quelque chose au xml. – Ace

+0

Voulez-vous une solution XSLT qui mettra des caractères à espace zéro dans le texte? Si oui, pouvez-vous fournir le plus petit exemple possible de votre XSL-FO et quel texte/où vous devez rendre splittable? –

Répondre

15

Dans les mots longs, essayez d'insérer un zero-width space character entre les caractères où une pause est autorisée.

+0

@mzjin: Impossible d'ajouter ce caractère manuellement, car la largeur de la colonne est inconnue et l'entrée elle-même est générée à l'exécution – Ace

+0

@mzjin: J'utilise la solution 1 et je suis très proche, voir la modification de mon répondre. – Ace

+0

Vous devez vous assurer que le modèle s'applique uniquement aux cellules de tableau. Essayez ''. – mzjn

4

Puisque vous utilisez XSLT 2.0:

<xsl:template match="text()"> 
    <xsl:value-of 
     select="replace(replace(., '(\P{Zs})(\P{Zs})', '$1&#x200B;$2'), 
         '([^\p{Zs}&#x200B;])([^\p{Zs}&#x200B;])', 
         '$1&#x200B;$2')" /> 
</xsl:template> 

Cette catégorie utilise échappe (http://www.w3.org/TR/xmlschema-2/#nt-catEsc) plutôt que d'une liste explicite de caractères pour correspondre, mais vous pouvez le faire de cette façon à la place. Il a besoin de deux replace() parce que le replace() interne peut seulement insérer le caractère entre chaque deuxième caractère. Le replace() extérieur correspond à des caractères qui ne sont pas des caractères d'espace ou le caractère ajouté par le replace() intérieur.


Insertion après chaque treizième caractère non-espace:

<xsl:template match="text()"> 
    <xsl:value-of 
     select="replace(replace(., '(\P{Zs}{13})', '$1&#x200B;'), 
         '&#x200B;(\p{Zs})', 
         '$1')" /> 
</xsl:template> 

Les replace() internes insère le caractère après tous les 13 caractères non-espace, et les replace() extérieures fixe si le 14e caractère était un espace personnage.


Si vous utilisez AH Formatter, vous pouvez utiliser axf:word-break="break-all" pour permettre AH Formatter de briser n'importe où dans un mot. Voir https://www.antennahouse.com/product/ahf64/ahf-ext.html#axf.word-break.