XSL-FO - 如何生成目录?

时间:2011-09-02 13:37:45

标签: xml xslt xsl-fo

我有以下文档结构,我想生成一个适合我的XSLT转换的目录。我尝试了很多东西,但没有一个能为我工作。有人可以帮我吗?

通过以下转换,我得到了这个警告和空白页码。

 WARNING: Page 2: Unresolved id reference "N65898" found.

Document structure

<article>
    <chapter>
        <title>Chapter 1</title>
        <para>chapter 1 text</para>
        <sect1>
            <title>Section1 1.1</title>
            <para>text 1.1</para>
            <sect2>
                <title>Section2 1.1.1</title>
                <para>text 1.1.1</para>
            </sect2>
            <sect2>
                <title>Section2 1.1.2</title>
                <para>text 1.1.2</para>
            </sect2>
            <sect2>
                <title>Section2 1.1.3</title>
                <para>text 1.1.3</para>
            </sect2>
            <sect2>
                <title>Section2 1.1.4</title>
                <para>text 1.1.4</para>
            </sect2>
        </sect1>
        <sect1>
            <title>Section1 1.2</title>
            <sect2>
                <title>Section2 1.2.1</title>
            </sect2>
            <sect2>
                <title>Section2 1.2.2</title>
                <sect3>
                    <title>Section3 1.2.2.1</title>
                </sect3>
                <sect3>
                    <title>Section3 1.2.2.2</title>
                </sect3>
            </sect2>
        </sect1>
    </chapter>
    <chapter>
        <title>Chapter 2</title>
        <sect1>
            <title>Section1 2.1</title>
            <sect2>
                <title>Section2 2.1.1</title>
            </sect2>
            <sect2>
                <title>Section2 2.1.2</title>
                <sect3>
                    <title>Section3 2.1.2.1</title>
                </sect3>
                <sect3>
                    <title>Section3 2.1.2.2</title>
                </sect3>
            </sect2>
        </sect1>
        <sect1>
            <title>Section1 2.2</title>
            <sect2>
                <title>Section2 2.2.1</title>
            </sect2>
            <sect2>
                <title>Section2 2.2.2</title>
                <sect3>
                    <title>Section3 2.2.2.1</title>
                </sect3>
                <sect3>
                    <title>Section3 2.2.2.2</title>
                </sect3>
            </sect2>
        </sect1>
    </chapter>
    <chapter>
        <title>Chapter 3</title>
        <sect1>
            <title>Section1 3.1</title>
            <sect2>
                <title>Section2 3.1.1</title>
            </sect2>
            <sect2>
                <title>Section2 3.1.2</title>
                <sect3>
                    <title>Section3 3.1.2.1</title>
                </sect3>
                <sect3>
                    <title>Section3 3.1.2.2</title>
                </sect3>
            </sect2>
        </sect1>
        <sect1>
            <title>Section1 3.2</title>
            <sect2>
                <title>Section2 3.2.1</title>
            </sect2>
            <sect2>
                <title>Section2 3.2.2</title>
                <sect3>
                    <title>Section3 3.2.2.1</title>
                </sect3>
                <sect3>
                    <title>Section3 3.2.2.2</title>
                </sect3>
            </sect2>
        </sect1>
    </chapter>
</article>

Transformation

<!-- table of contents -->
<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">
            <fo:basic-link internal-destination="{generate-id(.)}">
                <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="{generate-id(.)}" />
            </fo:basic-link>
        </fo:block>
    </xsl:for-each>
</fo:block>

1 个答案:

答案 0 :(得分:7)

只有在输出<chapter>时输出ID才会有效。 @ref-id中的<fo:page-number-citation>需要指出一些内容。

请参阅我的回答here


编辑 - 生成ID的示例

这是一个示例样式表。它将从您的输入XML生成带有工作TOC的PDF。我用Saxon 6.5.5和FOP进行了测试。

<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="/article">
    <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">
           <xsl:call-template name="genTOC"/>
         </fo:flow>
        </fo:page-sequence>
        <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">
          <fo:basic-link internal-destination="{generate-id(.)}">
            <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="{generate-id(.)}" />
          </fo:basic-link>
        </fo:block>
      </xsl:for-each>
    </fo:block>
  </xsl:template>

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

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

</xsl:stylesheet>