xsl-fo 不分页_使用XSL-FO进行分页符和表格

本文介绍了XSL-FO在处理分页时遇到的问题,如标题和图像分页不当,并提供了使用keep属性以及FOP的解决方法,包括盲表技术来确保内容完整性。
摘要由CSDN通过智能技术生成

xsl-fo 不分页

XSL格式设置对象(XSL-FO)标准是XSL标准中鲜为人知的部分之一(最突出的部分是XSLT)。 这是不幸的,因为XSL-FO对于诸如从XML文档生成PDF或Postscript文件之类的任务非常有用。 一般来说,XSL-FO控制XML文档的布局和表示。 实际上,大多数用户发现HTML页面适合在屏幕上阅读,但他们更喜欢PDF(因此也称为XSL-FO)作为打印副本。

控制分页符

XSL-FO的优点之一是,它可以根据需要自动将文档的文本放置在尽可能多的页面上。 页面装满后,XSL-FO会自动插入下一页。 不幸的是,该算法有时可能在错误的位置插入分页符,例如节标题和节内容之间的中断。 同样,它有时会将图形标签与实际图像分开,或将表标题与表行分开。

图1和图2说明了该问题。 在图1中,节标题位于页面底部,而节的其余部分位于下一页。

图1.部分标题后的分页符不合适
分节标题后的分页符

在图2中,图像标签已与图像分离。

图2.图像标签后的不适当的分页符
标签图片后分页

之所以会出现问题,是因为XSL-FO渲染器具有许多可使用的块,并且它不知道它们之间的关系。 它不知道标题是。 。 。 好吧,一个标题。 解决方案是告诉XSL-FO渲染器哪些块相互关联,或更具体地说,哪些块应保持在一起。 为此,该标准在keep and break类别中定义了几个属性。 keep-with-previouskeep-with-next属性指定是将一个块保留在上一个块还是下一个块。

该属性适用within-linewithin-columnwithin-page组件。 顾名思义,这些组件控制应将块分组的级别。 通常,我使用within-page组件。

可接受的值为auto (无特殊处理), always (始终将块保留在同一页面上)或整数。 整数指定优先级,因此如果多个keep属性发生冲突,则数字优先级最高的优先。 总体而言, always值具有最高优先级。

清单1是一个样式表的摘录,该样式表使用keep属性来防止标题和段落之间的中断或标签与图像之间的中断。 在XSL-FO中,该属性是一个属性。 (请参阅相关主题下载同伴代码的完整样式表)。

清单1. keep属性
<xsl:template match="doc:title" mode="keep">
   <fo:block font-family="Times Roman"
             font-size="12pt"
             space-after="0.6em"
             keep-with-next.within-page="always">
      <xsl:apply-templates mode="keep"/>
   </fo:block>
</xsl:template>

<xsl:template match="doc:figure" mode="keep">
   <fo:block font-family="Times Roman"
             font-size="8pt"
             font-style="italic"
             space-after="0.5em">
      <xsl:value-of select="@label"/>
   </fo:block>
   <fo:block keep-with-previous.within-page="always">
      <fo:external-graphic src="url({@src})"
                           width="{@width}"
                           height="{@height}"/>
   </fo:block>
</xsl:template>

但是请注意,FOP(格式化对象处理器,Apache的开源XSL处理器)不能完全实现keep属性。 如果使用清单1 ,则FOP会忽略keep属性,这仍然可能导致不适当的分页符。 据我所知,唯一的商业渲染器,如XEP从RenderX或天线府XSL格式化(参见相关主题 )实现keep性能-在写这篇文章的时间最少。

FOP解决方法

鉴于商业实现为标准提供了更完整的支持,因此购买副本可能是目前最好的解决方案。 不过,每台服务器的许可费用约为5,000美元(尽管有限的工作站许可价格可低至79美元),并非每个项目都能负担得起自己的XSL-FO渲染器。 在预算有限的项目早期阶段尤其如此。

尽管可以使用将FOP keep属性用于解决方案,但这只是部分解决方案。 FOP仅识别表行的keep属性。 有限的支持对于将表标题与表的其余部分组合在一起很有用,但是它也提供了一种变通方法,直到可以得到完全的支持为止。 该解决方案依赖于所谓的盲表 (专门为布局而引入的表,但实际上并不可见)。 如果您已完成任何HTML编码,则应该已经熟悉将表仅用于布局(例如,模拟列)。

清单2是另一个样式表摘录,它演示了使用FOP在盲表中的keep属性。 此版本的样式表可防止出现不适当的分页符。 doc:figure的模板创建一个盲表,在第一行带有标签,在第二行带有图像。 keep-with-previous属性应用于第二行。

清单2.盲表
<xsl:template match="doc:figure" mode="blind">
   <fo:table table-layout="fixed" width="100%">
      <fo:table-column column-width="proportional-column-width(1)"/>
      <fo:table-body>
         <fo:table-row padding-bottom="0.5em">
            <fo:table-cell>
               <fo:block font-family="Times Roman"
                         font-style="italic"
                         font-size="8pt">
                  <xsl:value-of select="@label"/>
               </fo:block>
            </fo:table-cell>
         </fo:table-row>
         <fo:table-row keep-with-previous="always">
            <fo:table-cell>
               <fo:block>
                  <fo:external-graphic src="url({@src})"
                                       width="{@width}"
                                       height="{@height}"/>
                </fo:block>
            </fo:table-cell>
         </fo:table-row>
     </fo:table-body>
  </fo:table>
</xsl:template>

<xsl:template match="doc:section" mode="blind">
   <fo:table table-layout="fixed" width="100%">
      <fo:table-column column-number="1"/>
      <fo:table-body>
         <fo:table-row keep-with-next="always">
            <fo:table-cell>
               <xsl:apply-templates select="doc:title" mode="blind"/>
            </fo:table-cell>
         </fo:table-row>
         <fo:table-row>
            <fo:table-cell>
               <xsl:apply-templates select="*[2]" mode="blind"/>
            </fo:table-cell>
         </fo:table-row>
     </fo:table-body>
  </fo:table>
  <xsl:apply-templates select="*[position() > 2]" mode="blind"/>
</xsl:template>

doc:section模板类似。 再次,它将创建一个包含两行的盲表。 标题位于第一行,第一段位于第二行。 必须注意选择第一段。 我选择按位置选择段落以增加灵活性。

实际上,盲表最适合图形标签和表标题,而不是节标题。 FOP不愿意在单元格的中间中断,这意味着如果将较长的段落包含在盲表中,它将阻止中断。 反过来,这可能会导致分页符超出严格必要的范围。 您需要评估在文档中将该技术应用于何处。

一种改进可能是只为短段落生成一个盲表(您可以使用string-length()函数评估段落string-length() )。

摘要

借助XSL-FO,将XML文档转换为PDF并不困难,并且XSL-FO使您可以控制文档的最终布局,如本技巧演示所示。


翻译自: https://www.ibm.com/developerworks/xml/library/x-tippgbk/index.html

xsl-fo 不分页

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值