[xsl] managing footnotes in nested elements

Subject: [xsl] managing footnotes in nested elements
From: "Trevor Nicholls" <trevor@xxxxxxxxxxxxxxxxxx>
Date: Sat, 22 Sep 2007 01:55:09 +1200
Hi

Our documents can include footnotes almost anywhere, but on output (to HTML)
the footnotes can only appear in certain places - at the foot of maybe half
a dozen different elements (e.g. document, section, table). Footnote
elements include a level attribute which determines where the footnote
should appear.

Currently this is achieved with the following XSL 1.0 fragments:

<!-- ================================== -->

<!-- Where appropriate, a template which matches one of these
     major elements concludes with a call to a "local_footnotes"
     template which formats any of the footnotes found within
     that element.
  -->
<xsl:template match="...">
...
 <xsl:call-template name="local_footnotes" />
</xsl:template>

<!-- Only process footnotes within this element -->
<xsl:template name="local_footnotes">
 <xsl:variable name="local" select="name(.)" />
 <xsl:if test="descendant::footnote[@level=$local]">
  <div class="{$local}-footnotes">
   <xsl:apply-templates
       select="descendant::footnote[@level=$local]"
       mode="footnote"/>
  </div>
 </xsl:if>
</xsl:template>

<!-- Note:
     Following assumes footnote content can be placed
     within a para - so no complex footnote structure
     please!
  -->
<xsl:template match="footnote" mode="footnote">
<xsl:variable name="name">
  <xsl:text>fn</xsl:text>
  <xsl:call-template name="getid" />
 </xsl:variable>
 <a name="{$name}" />
 <p>
  <sup class="footnote-number">
   <xsl:apply-templates select="." mode="number" />
  </sup>
  <xsl:apply-templates />
 </p>
</xsl:template>

<!-- Footnotes follow a-1-i sequence -->
<xsl:template match="footnote" mode="number">
 <xsl:choose>
  <xsl:when test="@level='document'">
   <xsl:number level="any"
       count="footnote[@level='document']"
       from="document" format="a"/>
  </xsl:when>
  <xsl:when test="@level='section'">
   <xsl:number level="any"
       count="footnote[@level='section']"
       from="section" format="1"/>
  </xsl:when>
  <xsl:when test="@level='table'">
   <xsl:number level="any"
       count="footnote[@level='table']"
       from="table" format="i"/>
  </xsl:when>
 </xsl:choose>
</xsl:template>

<!-- ================================== -->

This is working wonderfully well provided that sections, tables, etc. are
not self-nested. (Z within Y within X is fine, X within X or Y within Y is
not).

So if a (large) table contains within itself a second (small) table which
contains a footnote, then the footnote appears twice: at the "foot" of the
small table and again at the "foot" of the large table.

How do I need to modify the above code in order to process these footnotes
correctly, please?

Thanks for any suggestions

Cheers
Trevor

Current Thread