XSL-FO 高级技术4

来源:互联网 发布:wifi无线上网软件 编辑:程序博客网 时间:2024/06/06 08:37
概述 第 1 页(共7 页)

既然您已经了解了定义打印页面外观的基本元素,现在让我们研究其它 XSL-FO 元素,这些元素可以使 PDF 文档看上去更专业。本章将讨论下列主题:

  • 定义多页布局
  • 添加页眉和页脚
  • 对页面编号
  • 用“Page x of y”样式对页面编号

用 XSL-FO 词汇表添加这些特性会比较简单。XSL-FO 元素是专门为上述的大多数任务设计的,FOP 工具为其余任务提供了一些扩展元素。


多页布局 第 2 页(共7 页)

本教程的第一个 XSL-FO 示例文档定义了单页布局。您往往希望文档的不同章节有不同的页面布局。例如,页号通常出现在页面底部,对于偶数页,出现在左边;对于奇数页,出现在右边。页眉通常不会在某一节的第一页上出现,但它们确实常常出现在该章节随后的页面上。

要处理文档基本布局上的这些变化,可以定义几个页面布局,然后描述每个布局的内容。下面是一个较复杂的 <fo:layout-master-set>,它包含三个 <fo:simple-page-master> 元素:

<fo:layout-master-set>  <fo:simple-page-master master-name="first"    margin-right="75pt" margin-left="75pt"    page-height="11in" page-width="8.5in"    margin-bottom="25pt" margin-top="75pt">    <fo:region-body margin-bottom="50pt"/>    <fo:region-after region-name="ra-right" extent="25pt"/>  </fo:simple-page-master>    <fo:simple-page-master master-name="left"    margin-right="75pt" margin-left="75pt"     page-height="11in" page-width="8.5in"    margin-bottom="25pt" margin-top="25pt">    <fo:region-before region-name="rb-left" extent="25pt"/>    <fo:region-body margin-top="50pt" margin-bottom="50pt"/>    <fo:region-after region-name="ra-left" extent="25pt"/>  </fo:simple-page-master>    <fo:simple-page-master master-name="right"    margin-right="75pt" margin-left="75pt"     page-height="11in" page-width="8.5in"    margin-bottom="25pt" margin-top="25pt">    <fo:region-before region-name="rb-right" extent="25pt"/>    <fo:region-body margin-top="50pt" margin-bottom="50pt"/>    <fo:region-after region-name="ra-right" extent="25pt"/>  </fo:simple-page-master>

该代码样本定义了三个名称分别为 firstleftright<fo:simple-page-master>。这些页面布局分别控制每章的第一页、左侧页面(偶数页)和右侧页面(奇数页)。

还请注意:代码将特定名称指定给页面布局的<fo:region-before><fo:region-after> 区域。您需要给这些区域起不同的名称,因为它们将有不同的内容。最后要说明的是:代码没有为第一页布局定义 <fo:region-before>,因为在章节标题之前不出现页眉。


页面布局序列 第 3 页(共7 页)

一旦定义了所有您需要的 <fo:simple-page-layout>,那么如何使用它们呢?答案在于 <fo:conditional-page-master-reference> 元素。下面是完整的 XSL-FO 结构,它用于定义一个页面布局序列:

    <fo:page-sequence-master master-name="standard">    <fo:repeatable-page-master-alternatives>      <fo:conditional-page-master-reference         master-reference="first" page-position="first"/>      <fo:conditional-page-master-reference         master-reference="left" odd-or-even="even"/>      <fo:conditional-page-master-reference         master-reference="right" odd-or-even="odd"/>    </fo:repeatable-page-master-alternatives>  </fo:page-sequence-master>      </fo:layout-master-set>

该示例定义一个名为 standard 的页面布局序列。它将名为 first 的页面布局用于第一页,将名为 left 的布局用于所有偶数页,将名为 right 的布局用于所有奇数页。(请注意:<fo:page-sequence-master> 与所有 <fo:simple-page-master> 一起出现在 <fo:layout-master-set> 元素内部。)

一旦定义了所有页面布局及何时使用它们后,可以使用<fo:page-sequence> 元素来着手编写文档内容。下面是一个简单的(不太有用)<fo:page-sequence> 元素:

<fo:page-sequence master-reference="standard">  <fo:flow flow-name="xsl-region-body">    ...  </fo:flow></fo:page-sequence> 

这不太有用,因为它对不同的页面布局不起任何作用。为了真正使 <fo:page-sequence> 能让 PDF 文件具有一个专业的外观,需要创建不同的页眉和页脚。


页眉和页脚 第 4 页(共7 页)

在先前对 <fo:region-body> 元素的描述(请参阅“XSL Formatting Objects basics”教程的“XSL-FO document function and structure”一节中的“<fo:region-body> 元素”)中,您学习了页面的五个区域。您已经了解了下面定义页面主区域内容的元素:

<fo:flow flow-name="xsl-region-body">  ...</fo:flow>

当使用 <fo:flow> 元素,而且 flow-namexsl-region-body 时,您告诉显示引擎:<fo:flow> 元素内的所有内容都是页面主体。要在页面上创建浮于文本主体上下的页眉和页脚,可以使用 <fo:static-content> 元素,flow-name 分别为 xsl-region-beforexsl-region-after

当然,这里的问题是这些名称是所有页面布局的通用区域名称。以前,当示例定义了所有 <fo:simple-page-layout> 时,它定义了四个不同的区域名称:

  • ra-left,用于左侧页面的 region-above
  • rb-left,用于左侧页面的 region-below
  • ra-right,用于右侧页面的 region-above
  • rb-right同时用于右侧页面和第一页的 region-below

请注意:该示例对右侧页面和第一页的 region-below 使用了相同的区域名称。因为那些区域的布局是相同的,所以不必给它们起不同的名称。

一旦定义了您所需要的页面区域,就可以定义这些区域中的内容了。为此使用 <fo:static-content> 元素。下面是用于其中两个区域(总共四个)的 <fo:static-content> 元素:

<fo:static-content flow-name="ra-right">  <fo:table font-size="10pt" text-align-last="end">    <fo:table-column column-width="350pt"/>    <fo:table-column column-width="75pt"/>    <fo:table-body>      <fo:table-row>        <fo:table-cell>          <fo:block text-align="start">            XSL Formatting Objects          </fo:block>        </fo:table-cell>        <fo:table-cell>          <fo:block text-align="end">Page             <fo:page-number/></fo:block>        </fo:table-cell>      </fo:table-row>    </fo:table-body>  </fo:table></fo:static-content><fo:static-content flow-name="rb-right">  <fo:table font-size="10pt" text-align-last="end">    <fo:table-column column-width="350pt"/>    <fo:table-column column-width="75pt"/>    <fo:table-body>      <fo:table-row>        <fo:table-cell>          <fo:block text-align="end">            Presented by your friends at developerWorks          </fo:block>        </fo:table-cell>        <fo:table-cell>          <fo:block text-align="start" font-weight="bold"             font-family="monospace">            ibm.com/developerWorks          </fo:block>        </fo:table-cell>      </fo:table-row>    </fo:table-body>  </fo:table></fo:static-content>

在这些区域中,表与文本对齐;第一个单元格是左对齐,而第二个单元格是右对齐。从理论上讲,在没有表的情况下也可以对齐文本(例如,使用 <fo:leader>),但我还不能使 FOP 和对齐功能一起使用。虽然它可能不太雅观,但该示例仍可以工作,这就是我们在 developerWorks 上所使用的。


 


页号 第 5 页(共7 页)

您可以已经在页眉和页脚中注意到:示例代码在页脚文本(区域名为 rb-right)中使用了一个新元素 <fo:page-number>。当由 FOP 进行处理,<fo:page-number> 元素被当前页号替换。这意味着标记类似于:

<fo:block>Page <fo:page-number/></fo:block>

生成的文本类似于:

Page 7

请注意:该示例将静态文本与 <fo:page-number> 元素一起使用来创建文本。如果需要使用其它编号方案(如字母字符或罗马数字),则使用 <fo:page-sequence> 元素的 format 属性。下面是一个示例:

<fo:page-sequence master-reference="standard" format="i"/> 

该代码告诉格式化引擎:应该将页面编号为 iiiiiiiv 等。注:FOP 不完全支持这种格式化;所有 <fo:page-number> 元素都使用您指定的格式,但 <fo:page-number-citation> 元素不使用该格式。这意味着对另一个页面的引用可能类似于 "See XYZ on page 28",而被引用的页面被编号为 xxviii


更改第一页编号 第 6 页(共7 页)

在某些情况下,您可能需要更改某一节的起始页号。XSL-FO 提供了 <fo:page-sequence> 元素的 initial-page-number 特性,尽管这还没有人所共知。它类似于:

<fo:page-sequence master-reference="standard"   initial-page-number="57"/>

该标记使编号页面从 57 开始。只要使用<fo:page-number><page-number-citation> 元素,那些值就将从 57 开始。


“Page x of y”的编号样式 第 7 页(共7 页)

对页面进行编号的常规方法是“Page 3 of 47”样式。当您不知道文档共有多少页时,您如何做到这种样式呢?答案是将带 id 的格式化对象放在 <fo:flow> 区域的末尾。然后,对出现在文档最后一页的标号块执行 <fo:page-number-citation>。标记类似于:

<fo:flow flow-name="xsl-region-body">  ... Lots and lots of content here  <fo:block id="TheVeryLastPage"> </fo:block></fo:flow>

代码创建 idTheVeryLastPage(任何人都不太可能使用的一个值)的块,现在可以引用该 id 来获得文档最后一页的页号。<fo:static-content> 区域中的内容应该类似于:

<fo:block text-align="end">  Page <fo:page-number/> of   <fo:page-number-citation     ref-id="TheVeryLastPage"/></fo:block>

当 FOP 格式化该标记时,它会生成类似“Page 4 of 28”的内容。


原创粉丝点击