0

I have the following definition for a table

      <fo:block font-size="10pt">
            <fo:table table-layout="fixed" width="100%" border-collapse="separate" border-separation="5pt"
                space-after="1.0cm">
                <fo:table-column column-width="3cm"/>
                <fo:table-column column-width="3cm"/>
                <fo:table-column column-width="3cm"/>
                <fo:table-column column-width="3cm"/>
                <fo:table-column column-width="3cm"/>
                <fo:table-column column-width="3cm"/>
                <fo:table-column column-width="3cm"/>
                <fo:table-footer>
            </fo:table>
        </fo:block>

How can I set each column to have max length and if it overflows it should go to the next line? Currently If the text in one column is extremely long it doesn't go to a next line and it is displayed on the same line which prevents seeing the other columns.

Example how data is mapped:

<xsl:template match="setInfo">
        <fo:table-row>
            <xsl:apply-templates select="." mode="font-weight"/>
            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="date"/>
                </fo:block>
            </fo:table-cell>
            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="category"/>
                </fo:block>
            </fo:table-cell>
                    <xsl:value-of select="measure"/>
            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="999999999999999999999999999999999999999999999999999999999999999999999999999999999"/>
                </fo:block>
            </fo:table-cell>
   </fo:table-row>
  </xsl:template>
lfurini
  • 3,729
  • 4
  • 30
  • 48
Joel
  • 85
  • 4
  • Can you include a sample of an `fo:table-cell` that does not wrap? It seems like you are using `linefeed-treatment="preserve"` or similar, but your current sample doesn't provide enough information to tell. Are there spaces in the text in the table cells? Which formatter are you using? – Tony Graham Feb 22 '22 at 23:48
  • I have added an example, there are no spaces and I am using Apache FOP – Joel Feb 23 '22 at 07:52

2 Answers2

1

Breaking text in table cells where the text does not have spaces is a common problem. The usual solution (for FOP) is to insert a zero-width space between characters. However, most of these answers use XSLT 2.0, while your question is tagged for XSLT 1.0:

Tony Graham
  • 7,306
  • 13
  • 20
  • Yes I am using XSLT 1.0 indeed, if I change my stylesheet element to be version 2.0 will it use XSLT 2.0 ? , like this : ``` ``` – Joel Feb 23 '22 at 08:23
  • 1
    You would need to use an XSLT processor that supports XSLT 2.0 or XSLT 3.0. Which XSLT processor are you using? Also, you don't want `exclude-result-prefixes="fo"`: you are generating elements in the FO namespace, so you do want the namespace declaration on the document element in your result. (You will get it anyway because the `` is in the FO namespace, so the XSLT processor has to generate the namespace declaration despite what you told it.) – Tony Graham Feb 23 '22 at 09:18
  • gave the result ```Apache Software Foundation ``` – Joel Feb 23 '22 at 10:10
  • 1
    It seems that you are using Xalan (https://xalan.apache.org/), which is an XSLT 1.0 processor. You would need to change to Saxon (http://www.saxonica.com) to use XSLT 2.0 or XSLT 3.0. – Tony Graham Feb 23 '22 at 10:36
  • How can I change the processor? I am using Java. – Joel Feb 23 '22 at 16:08
  • Get an XSLT 2.0 or XSLT 3.0 processor; e.g., by downloading Saxon. Run the XSLT processor on your source XML and your stylesheet to generate the FO file, then feed the FO file to FOP. I can't see from the FOP website how you'd change the XSLT processor that FOP uses when you feed it the XML and stylesheet. – Tony Graham Feb 23 '22 at 16:20
  • @Joel You can insert a zero-width space after every character (or after every n-th character) in XSLT 1.0 too. I know nothing about XSL-FO, but if you want, I can post a generic template that does that. – michael.hor257k Feb 24 '22 at 02:14
  • Maybe this can help too: https://stackoverflow.com/questions/19379070/how-to-change-apache-fop-xalan-xslt-processor – michael.hor257k Feb 24 '22 at 02:16
  • @michael.hor257k please post such a template – Joel Feb 24 '22 at 10:43
0

To insert a zero-width space character after every character of text (except the last one), replace your reference:

<xsl:value-of select="some-node"/>

with:

<xsl:call-template name="allow-line-breaks">
    <xsl:with-param name="text" select="some-node"/>
</xsl:call-template>

and add this template to your stylesheet:

<xsl:template name="allow-line-breaks">
    <xsl:param name="text"/>
    <xsl:value-of select="substring($text, 1, 1)"/>
    <xsl:if test="string-length($text) > 1">
        <xsl:text>&#8203;</xsl:text>
        <!-- recursive call -->
        <xsl:call-template name="allow-line-breaks">
            <xsl:with-param name="text" select="substring($text, 2)"/>
        </xsl:call-template>            
    </xsl:if>
</xsl:template>

P.S. As I noted in the comment to the other answer, I know nothing about XSL-FO. I cannot help wondering if there really isn't a built-in instruction to force line-wrap at column width.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51