jbrehr
jbrehr

Reputation: 815

XSL-FO page breaks, widows and orphans

I have a large corpus producing a PDF based on XSL-FO 3.0 transformation of the following simplified XML structure:

<corpus>
  <deposition>
     <text>
       <deposition-title>foo title</deposition-title>
       <seg>foo paragraph 1</seg>
       <seg>foo paragraph 2</seg>
       <seg>foo paragraph 3</seg>
       <appnotes>
         <appitem>foo apparatus item 1</appitem>
       </appnotes>
       <footnotes>
         <footitem>foo note 1</footitem>
         <footitem>foo note 1</footitem>
       </footnotes>
     </text>
  </deposition>
  <deposition>
     <text>
       <deposition-title>foo title</deposition-title>
       <seg>foo paragraph 1</seg>
       <seg>foo paragraph 2</seg>
      <appnotes/>
       <footnotes>
         <footitem>foo note 1</footitem>
       </footnotes>
     </text>
  </deposition>
   [...]
</corpus>

I use XSL-FO 3.0 that looks like the following (minus some inline markup for superscripts and italics):

<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:fo="http://www.w3.org/1999/XSL/Format" 
xmlns:xd="http://www.pnp-software.com/XSLTdoc"
version="3.0">

<xsl:template match="/">
    <fo:root>
        <fo:layout-master-set>
            <fo:simple-page-master 
                master-name="page-recto"
                page-height="29.7cm"  page-width="21cm"
                margin-top="2cm" margin-bottom="2cm" 
                margin-left="3cm" margin-right="1.5cm">
                <fo:region-body 
                    region-name="xsl-region-body"/>
            </fo:simple-page-master>
        </fo:layout-master-set>

        <fo:page-sequence master-reference="page-recto">
            <fo:flow flow-name="xsl-region-body" 
                font-family="Times" font-weight="normal" 
                font-size="8pt" space-before="8pt" space-after="8pt"
                text-align="justify" end-indent="120pt">
                <xsl:apply-templates/>
            </fo:flow>
        </fo:page-sequence>

    </fo:root>
</xsl:template>

<xsl:template match="text">
    <fo:block widows="10" orphans="10"
        font-size="9pt" font-weight="bold" 
        padding-bottom="1cm" end-indent="120pt">
        <xsl:apply-templates/>
    </fo:block>
</xsl:template>


<xsl:template match="seg">
    <fo:block
        font-family="Times" font-weight="normal" line-height="12pt" line-stacking-strategy="font-height"
        font-size="10pt" space-before="10pt" space-after="10pt" text-align="justify" end-indent="120pt">
        <xsl:apply-templates/>
    </fo:block>
</xsl:template>

<xsl:template match="appnotes">
   <xsl:choose>
       <xsl:when test="./appitem">
            <fo:leader leader-pattern="rule" leader-length="2cm" rule-style="solid" rule-thickness=".2pt"/>      
            <fo:block font-size="8pt" font-weight="normal" end-indent="120pt">
                <xsl:for-each select="./appitem">
                    <fo:inline keep-together="always"><xsl:apply-templates/>&#160;&#160;&#160;</fo:inline>
                </xsl:for-each>
            </fo:block></xsl:when>
       <xsl:otherwise></xsl:otherwise>
   </xsl:choose>
</xsl:template>

<xsl:template match="footnotes">
    <xsl:choose>
        <xsl:when test="./footitem">
            <fo:leader leader-pattern="rule" leader-length="2cm" rule-style="solid" rule-thickness=".2pt"/>  
                <xsl:for-each select="./footitem">
                    <fo:block font-size="8pt" font-weight="normal" end-indent="120pt">
                       <xsl:apply-templates/>
                    </fo:block>
                </xsl:for-each>
            <fo:leader leader-pattern="rule" leader-length="2cm" rule-style="solid" rule-thickness=".2pt"/>      
        </xsl:when>
        <xsl:otherwise>
            <fo:leader leader-pattern="rule" leader-length="2cm" rule-style="solid" rule-thickness=".2pt"/>      
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>

It produces repeatable sections like generally look like this:

Nice output, no  bad page breaks

But the XSL-FO produces some page break problems which I can't seem to solve using combinations of keep together, widows, orphans, etc.

<deposition-title> breaks from <seg>

Title split from content

<seg> breaks from <appnotes> and <footnotes>

Content split from appnotes/footnotes

Goals: I'd like to apply the following two rules for page breaking any <text>:

  1. <deposition-title> sticks to the first <seg>

  2. <appnotes> and <footnotes> sticks to the final <seg>

Thanks in advance for any insight.

Upvotes: 1

Views: 818

Answers (2)

jbrehr
jbrehr

Reputation: 815

In followup to the accepted answer, I'm posting the revised code here for the one problem identified in the comments. Now <appnotes>and <footnotes> are one template, inside one <fo:block>. This is processed with RenderX.

<xsl:template match="footnotes | appnotes">
    <fo:block font-size="8pt" font-weight="normal" end-indent="120pt" keep-with-previous="always">
        <xsl:choose>
            <xsl:when test="./appitem">
                <fo:leader leader-pattern="rule" leader-length="2cm" rule-style="solid" rule-thickness=".2pt" keep-with-previous="always"/>      
                <fo:block keep-with-previous="always">
                    <xsl:for-each select="./appitem">
                        <fo:inline><xsl:apply-templates/>&#160;&#160;&#160;</fo:inline>
                    </xsl:for-each>
                </fo:block>
            </xsl:when>
        </xsl:choose>
        <xsl:choose>
            <xsl:when test="./footitem">
                <fo:leader leader-pattern="rule" leader-length="2cm" rule-style="solid" rule-thickness=".2pt" keep-with-previous="always"/>  
                <xsl:for-each select="./footitem">
                    <fo:block keep-with-previous="always">
                        <xsl:apply-templates/>
                    </fo:block>
                </xsl:for-each>     
                <fo:leader leader-pattern="rule" leader-length="2cm" rule-style="solid" rule-thickness=".2pt" keep-with-previous="always"/> 
            </xsl:when>
        </xsl:choose>
    </fo:block>
</xsl:template>

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167401

If you add

<xsl:template match="deposition-title">
    <fo:block keep-with-next="always">
        <xsl:apply-templates/>
    </fo:block>
</xsl:template>

then the title should be put on the same page as the first seg block you produce.

A similar construction with keep-with-previous should do for the appnotes and footnotes, as I understand you want to keep them both together with the last seg block so perhaps changing the <xsl:apply-templates/> in the template matching text should be changed to <xsl:apply-templates select="node() except footnotes/> and then in the template matching appnotes you create the wrapper and process the footnotes e.g.

<xsl:template match="appnotes">
  <fo:block keep-with-previous="always">
    ...
    <xsl:apply-templates select="following-sibling::footnotes"/>
  </fo:block>
</xsl:template>

Upvotes: 3

Related Questions