如何在pdf生成之前预处理xsl:fo文档?

时间:2013-08-29 10:41:11

标签: xml xslt xml-parsing xsl-fo

考虑以下xml:

 <book>
    <chapter>
            <title>chapter title 1</title>
        <id>chapterId1</id>
        <content>some content</content> 
    </chapter>
    <chapter>
            <title>chapter title 2</title>
        <id>chapterId2</id>
        <content>some content</content> 
    </chapter>
</book>

我想生成一本包含目录的书。所以我像这样创建TOC:

<xsl:for-each select="book/chapter">
    <fo:block>
        <xsl:value-of select="title" />
            <fo:page-number-citation ref-id="id" >
                <xsl:attribute name="ref-id">
                    <xsl:value-of select="id" />
                </xsl:attribute>
            </fo:page-number>
    </fo:block>
</xsl:for-each>

动态覆盖ref-id属性,并替换为章节id的值。

这里的问题是引用的id在文档中还没有。因为我使用相同的<xsl:attribute>元素来创建cahpeter块上的章节id。

<fo:block> <!-- the chapter container -->
  <xsl:attribute name="id">
    <xsl:value-of select="chapter/id" />
  </xsl:attribute>
  <fo:block>
      the chapter content.....
  </fo:block>
</fo:block>

如何预处理我的xsl:fo文件,以便fo:block元素已经设置了正确的ID?

谢谢

1 个答案:

答案 0 :(得分:0)

您无需进行任何预处理。每个章节都需要由XSLT样式表处理两次:生成主要内容和生成TOC时。只需确保在两种情况下都使用相同的ID。

以下样式表说明了如何完成此操作(改编自this answer)。它适用于您的示例源文档。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
    <xsl:apply-templates select="node()|@*"/>
  </xsl:template>

  <xsl:template match="/book">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
       <fo:layout-master-set>
          <fo:simple-page-master master-name="my-page" page-width="8.5in" 
                                 page-height="11in">
             <fo:region-body margin="1in" margin-top="1.5in"/>
          </fo:simple-page-master>
       </fo:layout-master-set>
       <fo:page-sequence master-reference="my-page">
         <fo:flow flow-name="xsl-region-body">
         <!-- Call the template that generates the TOC -->
           <xsl:call-template name="genTOC"/>
         </fo:flow>
        </fo:page-sequence>
        <!-- Then output the main content -->
        <xsl:apply-templates/>
    </fo:root>
  </xsl:template>

  <xsl:template name="genTOC">
    <fo:block break-before='page'>
      <fo:block font-size="16pt" font-weight="bold">TABLE OF CONTENTS</fo:block>
      <xsl:for-each select="chapter">
        <fo:block text-align-last="justify">
            <xsl:value-of select="count(preceding::chapter) + 1" />
            <xsl:text> </xsl:text>
            <xsl:value-of select="title" />
            <fo:leader leader-pattern="dots" />
            <fo:page-number-citation ref-id="{id}" />
        </fo:block>
      </xsl:for-each>
    </fo:block>
  </xsl:template>

  <xsl:template match="title|content">
    <fo:block><xsl:value-of select="."/></fo:block>
  </xsl:template>

  <xsl:template match="chapter">
    <fo:page-sequence master-reference="my-page" id="{id}">
       <fo:flow flow-name="xsl-region-body">
         <xsl:apply-templates/>
       </fo:flow>
    </fo:page-sequence>
  </xsl:template>

</xsl:stylesheet>