Search code examples
xsltxsl-foantenna-house

Force line break after string length


I want to force a line break after a string length of 14 characters in a PDF generated with AH Formatter. So this is my xsl code without any attempt of line breaking:

<xsl:attribute-set name="big" use-attribute-sets="bold">
  <xsl:attribute name="font-size">38pt</xsl:attribute>
  <xsl:attribute name="line-height">28.84pt</xsl:attribute>
  <xsl:attribute name="text-align">center</xsl:attribute>
  <xsl:attribute name="letter-spacing">1mm</xsl:attribute>
</xsl:attribute-set>

<xsl:attribute-set name="small" use-attribute-sets="bold">
  <xsl:attribute name="font-size">27pt</xsl:attribute>
  <xsl:attribute name="line-height">27pt</xsl:attribute>
  <xsl:attribute name="text-align">center</xsl:attribute>
  <xsl:attribute name="letter-spacing">1mm</xsl:attribute>
</xsl:attribute-set>

<xsl:choose>
   <xsl:when test="string-length($count_cover)>=14">
      <fo:block xsl:use-attribute-sets="small">
         <xsl:apply-templates/>
      </fo:block>
    </xsl:when>
    <xsl:otherwise>          
      <fo:block xsl:use-attribute-sets="big">
         <xsl:apply-templates/>
      </fo:block>
   </xsl:otherwise>
</xsl:choose>

Is it possible to force a line break with XSL-FO?


Solution

  • If the title can be converted into string, you can insert <fo:block/> as line break.

    <xsl:variable name="cover_title" as="xs:string" select="'Very Long Cover Title! Very Long Cover Title! Very Long Cover Title! '"/>
    <xsl:variable name="count_cover" as="xs:integer" select="string-length($cover_title)"/>
    <xsl:variable name="lf_position" as="xs:integer" select="14"/>
    
    <xsl:template match="/">
        <xsl:choose>
            <xsl:when test="$count_cover gt $lf_position">
                <fo:block xsl:use-attribute-sets="small">
                    <xsl:analyze-string select="$cover_title" regex=".{{1}}">
                        <xsl:matching-substring>
                            <xsl:value-of select="."/>
                            <xsl:if test="position() eq $lf_position">
                                <fo:block/>
                            </xsl:if>
                        </xsl:matching-substring>
                        <xsl:non-matching-substring/>
                    </xsl:analyze-string>
                </fo:block>
            </xsl:when>
            <xsl:otherwise>
                <fo:block xsl:use-attribute-sets="big">
                    <xsl:value-of select="$cover_title"/>
                </fo:block>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    

    The result:

    <fo:block font-weight="bold" font-size="27pt" line-height="27pt" text-align="center" letter-spacing="1mm">Very Long Cove<fo:block/>r Title! Very Long Cover Title! Very Long Cover Title! </fo:block>
    

    However this method ignores word boundaries and hyphenation control. If you are intending to make book cover title, it will better to introduce AH Formatter extensions by using fo:block-container.

    1. Use fo:block-container for your title in fixed position and size in the cover page.
    2. Set property @overflow="condense" with @axf:overflow-condense=”font-size". https://www.antennahouse.com/product/ahf60/docs/ahf-ext.html#axf.overflow-condense
    3. Inside the fo:block-container, place fo:block that stores title contents.
    4. You can get desired result because AH Formatter automatically adjust the font-size according to the content volume.

    [Example]

    <fo:block-container position="absolute" top="..." left="..." width="..." height="..." overflow="condense" axf:overflow-condense="font-size" font-size="27pt" text-align="center">
        <fo:block>
           <fo:inline>Very Long Cover Title! Very Long Cover Title! Very Long Cover Title!</fo:inline>
        </fo:block>
    </fo:block-container>