Search code examples
xmlxsltxsl-fo

XSL:FO horizontal formatting, new line if doesn't fit


I have multiple blocks in my xsl file, which I want to be formatted in one line, but in case there's not enough space - blocks would move to the next line. Currently I have the following xsl block:

  <fo:static-content flow-name="header-continued">
   <fo:block-container>
    <fo:block>
      <xsl:for-each select="/myroot/category">
       <fo:inline>
         <xsl:value-of select="name"/>
       </fo:inline>
      </xsl:for-each>
    </fo:block>
   </fo:static-content>
  </fo:block-container>

Currently in case there's not enough width - content just gets cut on the left and right sides. Behavior I want is similar to HTML markup when there're several DIVs and they have display:inline-block style.


Solution

  • Some formatters when given this:

    <fo:inline>foo</fo:inline><fo:inline>foo</fo:inline><fo:inline>foo</fo:inline><fo:inline>foo</fo:inline><fo:inline>foo</fo:inline> 
    

    will not break between each of the elements. Thus, change your template to output a breaking space in between each <fo:inline>.

    See https://en.wikipedia.org/wiki/Zero-width_space

    The entity is &#8203;

    Like:

      <xsl:for-each select="/myroot/category">
       <fo:inline>
         <xsl:value-of select="name"/>
       </fo:inline>
       <xsl:text>&#8203;</xsl:text>
      </xsl:for-each>
    

    This should create a zero-width breaking space between each <fo:inline> to allow it to break for multiple lines.

    This assumes of course you want no space in between them.

    Now, that said, in the above template I would note that the <fo:inline> elements do absolutely nothing (except possibly cause the issue you have) as they carry no separate styles or anything.

    I would assume you would be happy with:

      <xsl:for-each select="/myroot/category">
         <xsl:value-of select="name"/>
      </xsl:for-each>
    

    Which in reality is exactly the same. And if your data looks like this:

    <name>foo</name>
    <name>bar</name>
    <name>foo</name>
    <name>bar</name>
    <name>foo</name>
    <name>bar</name>
    

    Then your output would be:

    foobarfoobarfoobar

    And then you can see why there are no breaks.