XSL-FO分页符,寡妇和孤儿

时间:2017-12-28 16:45:14

标签: xml xslt xsl-fo

我有一个大型语料库,根据以下简化XML结构的XSL-FO 3.0转换生成PDF:

<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>

我使用的XSL-FO 3.0如下所示(减去上标和斜体的内联标记):

<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>

它产生可重复的部分,如下所示:

Nice output, no  bad page breaks

但是XSL-FO产生了一些分页问题,​​我似乎无法使用保持在一起,寡妇,孤儿等组合来解决这些问题。

<deposition-title><seg>

中断

Title split from content

<seg><appnotes><footnotes>

中断

Content split from appnotes/footnotes

目标:我想应用以下两个规则来破解任何<text>

  1. <deposition-title>坚持第一个<seg>

  2. <appnotes><footnotes>坚持最后的<seg>

  3. 提前感谢任何见解。

2 个答案:

答案 0 :(得分:3)

如果你添加

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

然后标题应与您生成的第一个seg块放在同一页面上。

keep-with-previous的类似结构应该用于appnotes和脚注,因为据我所知,你想要将它们与最后一个seg块保持在一起,所以可能更改<xsl:apply-templates/>中的text模板匹配<xsl:apply-templates select="node() except footnotes/>应更改为appnotes,然后在匹配<xsl:template match="appnotes"> <fo:block keep-with-previous="always"> ... <xsl:apply-templates select="following-sibling::footnotes"/> </fo:block> </xsl:template> 的模板中创建包装并处理脚注,例如

Execute SQL Task

答案 1 :(得分:1)

在接受答案的后续内容中,我在此处针对评论中指出的一个问题发布了修订后的代码。现在<appnotes><footnotes>是一个模板,位于一个<fo:block>内。这是使用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>