How to force wrap on table entries

19,562

Solution 1

In the long words, try inserting a zero-width space character between the characters where a break is allowed.

Solution 2

Since you're using 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>

This is using category escapes (http://www.w3.org/TR/xmlschema-2/#nt-catEsc) rather than an explicit list of characters to match, but you could do it that way instead. It needs two replace() because the inner replace() can only insert the character between every second character. The outer replace() matches on characters that are not either space characters or the character added by the inner replace().


Inserting after every thirteenth non-space character:

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

The inner replace() inserts the character after every 13 non-space characters, and the outer replace() fixes it if the 14th character was a space character.


If you are using AH Formatter, then you can use axf:word-break="break-all" to allow AH Formatter to break anywhere within a word. See https://www.antennahouse.com/product/ahf64/ahf-ext.html#axf.word-break.

Share:
19,562
Ace
Author by

Ace

Updated on August 24, 2022

Comments

  • Ace
    Ace over 1 year

    I'm having an issue where when I publish my modspecs to pdf (XSL-FO). My tables are having issues, where the content of a cell will overflow its column into the next one. How do I force a break on the text so that a new line is created instead?

    I can't manually insert zero-space characters since the table entries are programmatically entered. I'm looking for a simple solution that I can just simply add to docbook_pdf.xsl (either as a xsl:param or xsl:attribute)

    EDIT: Here is where I'm at currently:

    <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>
    

    With this, the long words are successfully broken up in the table cells! Unfortunately, the side effect is that normal text elsewhere (like in a under sextion X) now breaks up words so that they appear on seperate lines. Is there a way to isolate the above process to just tables?