Question

I am creating a table of contents and a bookmark tree using Saxon (9.1) and FOP (0.95). Everything works fine, except for the following FOP output:

WARNING: 1 link target could not be resolved and now point to the top of the page or is dysfunctional.

In the resulting PDF, all links (from both TOC and bookmark tree) point to the first chapter. Why is that? Thank you for any help.

XML input file:

<?xml version="1.0"?>
<document>
 <header>
  <title>This is the title of the document</title>
  <author>Mathias Mueller</author>
  <date>29/10/2013</date>
 </header>
 <body>
  <chapter level="1">
   <chaptitle>This is the title of the first chapter.</chaptitle>
   <p>All Saints Day (also known as All Hallows, Solemnity of All Saints...</p>      
  </chapter>
  <chapter level="2">
   <chaptitle>This is the title of the second chapter.</chaptitle>
   <p>In Western Christian theology, the day commemorates ...</p>
   </chapter>
   <chapter level="2">
    <chaptitle>This is the title of the third chapter.</chaptitle>
    <p>The feast of All Saints achieved great prominence in the ninth century, in the reign of the Byzantine Emperor, Leo VI the Wise...</p>
   </chapter>
  </body>
 <documentProperties>
   <orientation>portrait</orientation>
   <format>A4</format>
 </documentProperties>
</document>

XSLT 2.0-Stylesheet (only attribute-sets defining block properties are left out)

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

<xsl:template match="document">
 <xsl:element name="fo:root" xmlns="http://www.w3.org/1999/XSL/Format">
  <xsl:call-template name="docPr"/>
  <xsl:call-template name="bmt"/>
  <!--page sequence for TOC-->
  <xsl:element name="fo:page-sequence">
   <xsl:attribute name="master-reference">A4portrait</xsl:attribute>
   <xsl:element name="fo:flow">
    <xsl:attribute name="flow-name">xsl-region-body</xsl:attribute>
    <xsl:call-template name="toc"/>
   </xsl:element>
  </xsl:element>
  <!--rest-->
  <xsl:apply-templates/>
 </xsl:element>  
</xsl:template>

<xsl:template name="docPr">
 <xsl:element name="fo:layout-master-set">
  <xsl:if test="documentProperties/orientation eq 'portrait' and documentProperties/format eq 'A4'">
   <xsl:element name="fo:simple-page-master" use-attribute-sets="A4portrait">
    <xsl:element name="fo:region-body">
     <xsl:attribute name="margin-top">25mm</xsl:attribute>
     <xsl:attribute name="margin-bottom">20mm</xsl:attribute>
    </xsl:element>
   </xsl:element>
  </xsl:if>
 </xsl:element>
</xsl:template>

<xsl:template name="bmt">
 <xsl:element name="fo:bookmark-tree">
  <xsl:for-each select="body/chapter">
   <xsl:element name="fo:bookmark">
    <xsl:attribute name="internal-destination">{generate-id()}</xsl:attribute>
    <xsl:element name="fo:bookmark-title">
     <xsl:value-of select="chaptitle"/>
    </xsl:element>
   </xsl:element>
  </xsl:for-each>
 </xsl:element>
</xsl:template>

<xsl:template name="toc">
 <xsl:element name="fo:block">
  <xsl:attribute name="break-before">page</xsl:attribute>
   <xsl:element name="fo:block" use-attribute-sets="title2-block">
    <xsl:text>Table of Contents</xsl:text>
   </xsl:element>
   <xsl:for-each select="body/chapter">
    <xsl:element name="fo:block">
     <xsl:attribute name="text-align-last">justify</xsl:attribute>
     <xsl:element name="fo:basic-link">
      <xsl:attribute name="internal-destination">{generate-id()}</xsl:attribute>
      <xsl:value-of select="count(preceding::chapter) + 1"/>
      <xsl:text> </xsl:text>
      <xsl:value-of select="chaptitle"/>
      <xsl:element name="fo:leader">
       <xsl:attribute name="leader-pattern">dots</xsl:attribute>
      </xsl:element>
      <xsl:element name="fo:page-number-citation">
       <xsl:attribute name="ref-id">{generate-id()}</xsl:attribute>
      </xsl:element>
     </xsl:element>
    </xsl:element>
   </xsl:for-each>
  </xsl:element>
</xsl:template>


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

<xsl:template match="chaptitle">
 <xsl:element name="fo:block" use-attribute-sets="title1-block">
  <xsl:value-of select="."/>
 </xsl:element>
</xsl:template>

<xsl:template match="p">
 <xsl:element name="fo:block" use-attribute-sets="normal-block">
  <xsl:value-of select="."/>
 </xsl:element>
</xsl:template>
Was it helpful?

Solution

I think the problem is the way you call the XSLT generate-id() function. The syntax with brackets {} usually only works inside "" quotes. What now happens is that all ids are assigned the literal string {generate-id()}. I would suggest that you replace these occurences by <xsl:value-of select="generate-id()"/> and try again.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top