Search code examples
xsltxsl-fo

How to cut a long string into fixed length lines in XSL FO?


This is just info sharing. I already know the solution :) I did it the hard way !! I want two things here:

  1. To share what I reached so far.
  2. To know if anyone has a better solution

Solution

  • <xsl:template name="break-to-length">
        <xsl:param name="text" />
        <xsl:param name="length" />
        
        <xsl:variable name="first-half" select="substring($text,0,$length)" />
        <xsl:variable name="second-half" select="substring-after($text, $first-half)" />
        
        <xsl:variable name="last-five-chars-of-first-half" select="substring-after($first-half,substring($first-half, 0, $length - 5))" />
        
        <xsl:variable name="alternative-first-half">
            <xsl:choose>
                <xsl:when test="contains($last-five-chars-of-first-half, $space)">
                    <xsl:value-of select="concat(substring($first-half, 0, $length - 5), substring-before($last-five-chars-of-first-half, $space))" />
                </xsl:when>
                <xsl:when test="contains($last-five-chars-of-first-half, $dot)">
                    <xsl:value-of select="concat(substring($first-half, 0, $length - 5), substring-before($last-five-chars-of-first-half, $dot), $dot)" />
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$first-half" />
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        
        <xsl:variable name="alternative-second-half">
            <xsl:choose>
                <xsl:when test="contains($last-five-chars-of-first-half, $space)">
                    <xsl:value-of select="concat(substring-after($last-five-chars-of-first-half, $space), $second-half)" />
                </xsl:when>
                <xsl:when test="contains($last-five-chars-of-first-half, $dot)">
                    <xsl:value-of select="concat(substring-after($last-five-chars-of-first-half, $dot), $second-half)" />
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$second-half" />
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        
        <!-- if first half doesn't end with a space or dot -->
        <xsl:variable name="word-was-cut" select="$alternative-first-half = $first-half" />
        
        <xsl:value-of select="$alternative-first-half" />
        
        <xsl:choose>
            <xsl:when test="string-length($alternative-second-half) = 0">
                <!-- Do Nothing -->
            </xsl:when>
            <xsl:when test="string-length($alternative-second-half) &lt; $length">
                <!-- if first half doesn't end with a space or dot -->
                <xsl:if test="$word-was-cut">
                    <xsl:text>-</xsl:text>
                </xsl:if>
                <fo:block />
                <xsl:value-of select="$alternative-second-half" />
            </xsl:when>
            <xsl:otherwise>
                <!-- Second half is longer than max length -->
                <!-- if first half doesn't end with a space -->
                <xsl:if test="$word-was-cut">
                    <xsl:text>-</xsl:text>
                </xsl:if>
                <fo:block />
                <xsl:call-template name="break-to-length">
                    <xsl:with-param name="text" select="$alternative-second-half"/>
                    <xsl:with-param name="length" select="$length" />
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>