Tweaking XSL to preserve line breaks for XSL:FO using Apache FOP

I am a relative XSLT neophyte who is taking the plunge into XSL:FO using Apache FOP.  I've managed to figure out headers, footers, mixing single and double-column layout on the same page, and a few other goodies.  One last thing is holding me back -- preserving line breaks in the source data.  Attached are sample XML and XSL files that illustrate my problem.  The <data> section is populated by the application, and as you can see in the example, this particular PAYMENT_SCHEDULE has embedded line breaks.  (There are other fields with similar requirements, so please don't tell me to reformat the payment schedule.)

From Googling, I know that each line must somehow be wrapped in a <fo:block> tag in order to preserve the line breaks, but I just can't seem to figure out how to do it.  If you can show me how to fix this sample either by modifying the contents of the <field name="PAYMENT_SCHEDULE"> tag or by modifying the XSL file, I would greatly appreciate it!  Thank you in advance!
Sample.xml:

<?xml version="1.0" encoding="UTF-8"?>
<document>
  <data>
    <row>
      <field name="COMPANY">Acme Rocket Sleds, LLC</field>
      <field name="DOCUMENT_NUMBER">12345</field>
      <field name="AMOUNT_FINANCED">$ 50,000.00</field>
      <field name="PAYMENT_SCHEDULE">5 Quarterly payments, plus any applicable taxes, payable in advance as follows:
    1 - 1 : $35,000.00
    2 - 5 : $8.552.07</field>
      <field name="COMMENCEMENT_DATE">January 1, 2010</field>
    </row>
  </data>

  <content>
    <contract-header/>
  </content>
      
</document>


Sample.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format">
 
 <xsl:template match="/">
 
 <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
 
   <fo:layout-master-set>

       <fo:simple-page-master page-height="11in" page-width="8.5in" master-name="only">
         <fo:region-body region-name="xsl-region-body" margin="0.7in"/>
         <fo:region-before extent="0.7in"/>
         <fo:region-after extent="0.7in"/>
       </fo:simple-page-master>
   </fo:layout-master-set>

   <fo:page-sequence master-reference="only">
       <fo:flow flow-name="xsl-region-body">
          <xsl:apply-templates select="document/content"/>
       </fo:flow>
   </fo:page-sequence>

 </fo:root> 
 </xsl:template>
 
 <xsl:template match="content">
       <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="contract-header">
       <fo:block id="Contract Header" span="all" font-family="serif" font-size="9pt">
       <fo:table border="1.5pt solid black" border-spacing="2pt" table-layout="fixed" width="100%">
         <fo:table-column column-width="25%"/>
         <fo:table-column column-width="35%"/>
         <fo:table-column column-width="6%"/>
         <fo:table-column column-width="34%"/>
         <fo:table-body>
           <fo:table-row>
             <fo:table-cell border="0.5pt solid black">
               <fo:block>Contract #:</fo:block>
             </fo:table-cell>
             <fo:table-cell border="0.5pt solid black">
               <fo:block font-weight="bold"><xsl:value-of select="/document/data/row/field[@name='DOCUMENT_NUMBER']"/></fo:block>
             </fo:table-cell>
             <fo:table-cell border="0.5pt solid black">
               <fo:block>Dated:</fo:block>
             </fo:table-cell>
             <fo:table-cell border="0.5pt solid black">
               <fo:block font-weight="bold"><xsl:value-of select="/document/data/row/field[@name='COMMENCEMENT_DATE']"/></fo:block>
             </fo:table-cell>
           </fo:table-row>
           <fo:table-row>
             <fo:table-cell border="0.5pt solid black">
               <fo:block>Company:</fo:block>
             </fo:table-cell>
             <fo:table-cell border="0.5pt solid black" number-columns-spanned="3">
               <fo:block font-weight="bold">
                 <xsl:value-of select="/document/data/row/field[@name='COMPANY']"/>
               </fo:block>
             </fo:table-cell>
           </fo:table-row>
           <fo:table-row>
             <fo:table-cell border="0.5pt solid black">
               <fo:block>Original Cost and Fees of Products:</fo:block>
             </fo:table-cell>
             <fo:table-cell border="0.5pt solid black" number-columns-spanned="3">
               <fo:block><xsl:value-of select="/document/data/row/field[@name='AMOUNT_FINANCED']"/></fo:block>
             </fo:table-cell>
           </fo:table-row>
           <fo:table-row>
             <fo:table-cell border="0.5pt solid black">
               <fo:block>Payments due under this IPA:</fo:block>
             </fo:table-cell>
             <fo:table-cell border="0.5pt solid black" number-columns-spanned="3">
               <fo:block><xsl:value-of select="/document/data/row/field[@name='PAYMENT_SCHEDULE']"/></fo:block>
             </fo:table-cell>
           </fo:table-row>
           <fo:table-row>
             <fo:table-cell border="0.5pt solid black">
               <fo:block>Guarantor (if any):</fo:block>
             </fo:table-cell>
             <fo:table-cell border="0.5pt solid black" number-columns-spanned="3">
               <fo:block></fo:block>
             </fo:table-cell>
           </fo:table-row>
         </fo:table-body>
       </fo:table>
       </fo:block>
 </xsl:template>
 
 </xsl:stylesheet>

Open in new window

arktechAsked:
Who is Participating?
 
Geert BormansConnect With a Mentor Information ArchitectCommented:
Hey, sounds like you can use a recursive function to get all the new-lines and create blocks
<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
    <xsl:output indent="yes"/>
    <xsl:template match="/"> 
        
        <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
            
            <fo:layout-master-set> 
                
                <fo:simple-page-master page-height="11in" page-width="8.5in" master-name="only"> 
                    <fo:region-body region-name="xsl-region-body" margin="0.7in"/> 
                    <fo:region-before extent="0.7in"/> 
                    <fo:region-after extent="0.7in"/> 
                </fo:simple-page-master> 
            </fo:layout-master-set> 
            
            <fo:page-sequence master-reference="only"> 
                <fo:flow flow-name="xsl-region-body"> 
                    <xsl:apply-templates select="document/content"/> 
                </fo:flow> 
            </fo:page-sequence> 
            
        </fo:root>  
    </xsl:template> 
    
    <xsl:template match="content"> 
        <xsl:apply-templates/> 
    </xsl:template> 
    
    <xsl:template match="contract-header"> 
        <fo:block id="Contract Header" span="all" font-family="serif" font-size="9pt"> 
            <fo:table border="1.5pt solid black" border-spacing="2pt" table-layout="fixed" width="100%"> 
                <fo:table-column column-width="25%"/> 
                <fo:table-column column-width="35%"/> 
                <fo:table-column column-width="6%"/> 
                <fo:table-column column-width="34%"/> 
                <fo:table-body> 
                    <fo:table-row> 
                        <fo:table-cell border="0.5pt solid black"> 
                            <fo:block>Contract #:</fo:block> 
                        </fo:table-cell> 
                        <fo:table-cell border="0.5pt solid black"> 
                            <fo:block font-weight="bold"><xsl:value-of select="/document/data/row/field[@name='DOCUMENT_NUMBER']"/></fo:block> 
                        </fo:table-cell> 
                        <fo:table-cell border="0.5pt solid black"> 
                            <fo:block>Dated:</fo:block> 
                        </fo:table-cell> 
                        <fo:table-cell border="0.5pt solid black"> 
                            <fo:block font-weight="bold"><xsl:value-of select="/document/data/row/field[@name='COMMENCEMENT_DATE']"/></fo:block> 
                        </fo:table-cell> 
                    </fo:table-row> 
                    <fo:table-row> 
                        <fo:table-cell border="0.5pt solid black"> 
                            <fo:block>Company:</fo:block> 
                        </fo:table-cell> 
                        <fo:table-cell border="0.5pt solid black" number-columns-spanned="3"> 
                            <fo:block font-weight="bold"> 
                                <xsl:value-of select="/document/data/row/field[@name='COMPANY']"/> 
                            </fo:block> 
                        </fo:table-cell> 
                    </fo:table-row> 
                    <fo:table-row> 
                        <fo:table-cell border="0.5pt solid black"> 
                            <fo:block>Original Cost and Fees of Products:</fo:block> 
                        </fo:table-cell> 
                        <fo:table-cell border="0.5pt solid black" number-columns-spanned="3"> 
                            <fo:block><xsl:value-of select="/document/data/row/field[@name='AMOUNT_FINANCED']"/></fo:block> 
                        </fo:table-cell> 
                    </fo:table-row> 
                    <fo:table-row> 
                        <fo:table-cell border="0.5pt solid black"> 
                            <fo:block>Payments due under this IPA:</fo:block> 
                        </fo:table-cell> 
                        <fo:table-cell border="0.5pt solid black" number-columns-spanned="3"> 
                            <xsl:call-template name="replace-new-line">
                                <xsl:with-param name="str" select="/document/data/row/field[@name='PAYMENT_SCHEDULE']"/>
                            </xsl:call-template>
                        </fo:table-cell> 
                    </fo:table-row> 
                    <fo:table-row> 
                        <fo:table-cell border="0.5pt solid black"> 
                            <fo:block>Guarantor (if any):</fo:block> 
                        </fo:table-cell> 
                        <fo:table-cell border="0.5pt solid black" number-columns-spanned="3"> 
                            <fo:block></fo:block> 
                        </fo:table-cell> 
                    </fo:table-row> 
                </fo:table-body> 
            </fo:table> 
        </fo:block> 
    </xsl:template> 
    
    <xsl:template name="replace-new-line">
        <xsl:param name="str"/>
        <xsl:choose>
            <xsl:when test="contains($str, '&#10;')">
                <fo:block>
                    <xsl:value-of select="normalize-space(substring-before($str, '&#10;'))"/>
                </fo:block>
                <xsl:call-template name="replace-new-line">
                    <xsl:with-param name="str" select="substring-after($str, '&#10;')"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <fo:block>
                    <xsl:value-of select="normalize-space($str)"/>
                </fo:block>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Open in new window

0
 
arktechAuthor Commented:
Perfect!  That is exactly the type of solution I was hoping for!  Great answer, Gertone!
0
 
Geert BormansInformation ArchitectCommented:
welcome
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.