使用fop创建包含内容表的多页pdf

时间:2014-07-31 07:45:46

标签: xslt pdf xsl-fo apache-fop

假设输入XML文档如下:

<AuthorList>
  <Author>
    <name>John Steinbeck</name>
    <biography>John Ernst Steinbeck, Jr. (February 27, 1902 – December 20, 1968) was an American author of twenty-seven books, including sixteen novels, six non-fiction books
    </biography>
    <picture>
      http://upload.wikimedia.org/wikipedia/commons/e/e7/John_Steinbeck_1962.jpg
    </picture>
  </Author>
  <Author>
    <name>William Faulkner</name>
    <biography>William Cuthbert Faulkner (September 25, 1897 – July 6, 1962) was an American writer and Nobel Prize laureate from Oxford, Mississippi.
    </biography>
    <picture>
      http://upload.wikimedia.org/wikipedia/commons/f/f3/William_Faulkner_1949.jpg
    </picture>
  </Author>
</AuthorList>

我想创建一个PDF,第一页显示“种类”内容表,例如只是一个包含作者姓名的表和一个完整页面的内部链接。 PDF的其余部分应该是关于每个作者的详细表格,包含每个作者的生物,图片,等。 1页。

我已经编写了一段代码:

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

  <xsl:output method="xml" version="1.0" indent="yes" />
  <xsl:template match="AuthorList">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
      <fo:layout-master-set>
    <!-- Layout for the table of content -->
    <fo:simple-page-master master-name="table" page-height="29.7cm" page-width="21cm" margin="1cm">
      <fo:region-body column-count="1" background-color="transparent" />
      <fo:region-after extent="2cm" />
    </fo:simple-page-master>
    <!-- Layout for individual sheets -->
    <fo:simple-page-master master-name="sheet" page-height="21cm" page-width="29.7cm" margin="2cm">
      <fo:region-body column-count="1" background-color="transparent" />
    </fo:simple-page-master>
      </fo:layout-master-set>


      <!-- First part of the PDF output: table of content -->
      <fo:page-sequence master-reference="table">
    <fo:flow flow-name="xsl-region-body">
      <fo:block>
        Must put here the table of content
      </fo:block>
    </fo:flow>
      </fo:page-sequence>

      <!-- Second part of the PDF output: sheets for authors -->
      <xsl:apply-templates select="Author"/>

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


  <xsl:template match="Author">
    <fo:page-sequence master-reference="sheet">
      <fo:flow flow-name="xsl-region-body">
    <fo:block font-family="sans-serif" font-size="22pt" text-align="center">
      <xsl:apply-templates select="name" />
    </fo:block>

    <fo:block font-family="sans-serif" font-size="12pt" text-align="justify">
      <xsl:apply-templates select="biography" />
    </fo:block>
      </fo:flow>
    </fo:page-sequence>

  </xsl:template>

</xsl:stylesheet>

我现在面临一些问题:

  1. 如何在PDF的开头创建表格?我以为我可以有一个xsl:模板匹配作者来向表中添加行,但由于我已经有一个用于为作者生成详细表格,我怎么能区分他们两个?
  2. 如何将表格中元素的超链接引入每位作者的相应页面?
  3. 我也对改进建议感兴趣,例如:我把每个作者表放在页面序列中,但可能我不需要,尽管我希望每个作者页面都显示在它自己的页面中
  4. 我正在使用apache-fop来制作PDF。

    请注意,我完全掌握了原始XML的生成方式,因此如果有帮助,我可以更改结构。

1 个答案:

答案 0 :(得分:1)

有时候花些时间写一个合适的问题可以让你更准确地了解要寻找什么。我刚刚得知<xsl-template>有一个mode参数可以指定,所以我可以写

<xsl:template match="Author" mode="toc">
  <!-- write some code to put in the table of content -->  
</xsl:template>


<xsl:template match="Author" mode="sheet">
    <fo:page-sequence master-reference="sheet">
      <fo:flow flow-name="xsl-region-body">
    <fo:block font-family="sans-serif" font-size="22pt" text-align="center">
      <xsl:apply-templates select="name" />
    </fo:block>

    <fo:block font-family="sans-serif" font-size="12pt" text-align="justify">
      <xsl:apply-templates select="biography" />
    </fo:block>
      </fo:flow>
    </fo:page-sequence>

  </xsl:template>

我的调用代码变为

    <!-- First part of the PDF output: table of content -->
      <fo:page-sequence master-reference="table">
    <fo:flow flow-name="xsl-region-body">
      <fo:block>
         <xsl:apply-templates select="Author" mode="toc"/>
      </fo:block>
    </fo:flow>
      </fo:page-sequence>

      <!-- Second part of the PDF output: sheets for authors -->
      <xsl:apply-templates select="Author" mode="sheet"/>

关于我的第二个问题,我需要创建一个带有函数<fo:basic-link internal-destination="{generate-id(.)}">的链接(generate-id,因为名称表示生成id而不是使用硬编码的id)。另外,我使用id中的<fo-block>参数创建了链接目标,例如<fo:block id="{generate-id(.)}"> </fo:block>