Edit online

Use Case 2: Display Footnotes Below Tables

Suppose you want to separate the footnotes displayed in the WebHelp Responsive pages so that all footnotes are displayed at the end of the page except those within tables that are displayed just after them.

To add this functionality using a Oxygen Publishing Template, follow these steps:
  1. If you have not already created a Publishing Template, see How to Create a Publishing Template.
  2. Link the folder associated with the publishing template to your current project in the Project view.

    Step Result: You should have the custom_template folder linked in your project.

  3. Using the Project view, create an xsl folder inside the project root folder.

    Step Result: You should have the custom_template/xsl folder in your project.

  4. Create your customization stylesheet (for example, tablesFootnotes.xsl) in the custom_template/xsl folder with the following content:
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:oxy="http://www.oxygenxml.com/extensions/author"
      exclude-result-prefixes="#all"
      version="3.0">
    
      <!--
        Match only top level tables (i.e tables that are not nested in other tables),
        that contains some footnotes.
      -->
      <xsl:template match="
          *[contains(@class, 'topic/table')]
          [not(ancestor::*[contains(@class, 'topic/table')])]
          [//*[contains(@class, 'topic/fn')]]">
        <xsl:variable name="top-level-table" select="."/>
        <xsl:next-match>
          <xsl:with-param name="top-level-table" select="$top-level-table" tunnel="yes"/>
        </xsl:next-match>
        <!-- Create a list with all the footnotes from the current table. -->
        <div outputclass="table-fn-container">
          <xsl:for-each select=".//*[contains(@class, 'topic/fn')]">
            <!--
              Try to preserve the footnote ID, if available, so that the xrefs will have a target.
            -->
            <div id="{if(@id) then @id else generate-id(.)}">
              <xsl:variable name="unique-id" select="generate-id($top-level-table)"/>
              <xsl:variable name="fn-id">
                <xsl:number from="$top-level-table" level="any"/>
              </xsl:variable>
    
              <xsl:call-template name="commonattributes"/>
              <a name="tbl_{$unique-id}_fntarg_{$fn-id}" href="#tbl_{$unique-id}_fnsrc_{$fn-id}">
                <sup>
                  <xsl:value-of select="$fn-id"/>
                </sup>
              </a>
              <xsl:text>  </xsl:text>
    
              <xsl:apply-templates/>
            </div>
          </xsl:for-each>
        </div>
      </xsl:template>
    
      <!-- 
        Process footnotes both inside and outside tables (based on the top-level-table parameter).
      -->
      <xsl:template match="*[contains(@class, ' topic/fn ')]" name="topic.fn">
        <xsl:param name="xref"/>
        <xsl:param name="top-level-table" tunnel="yes"/>
        <!-- Footnotes with IDs must be ignored, they are accessible only through xrefs. -->
        <xsl:if test="not(@id) or $xref = 'yes'">
          <xsl:variable name="unique-id" select="
              if ($top-level-table) then
                generate-id($top-level-table)
              else
                ()"/>
          <xsl:variable name="fn-id" select="
              if ($top-level-table) then
                index-of($top-level-table//*[contains(@class, 'topic/fn')], .)
              else
                index-of(//*[contains(@class, 'topic/fn')]
                [not(ancestor::*[contains(@class, 'topic/entry')])], .)"/>
          <xsl:variable name="callout" select="@callout"/>
          <xsl:variable name="converged-callout" select="
              if (string-length($callout) > 0) then
                $callout
              else
                $fn-id"/>
          <a>
            <!-- Generate different attributes based on the presence of a parent table. -->
            <xsl:attribute name="name" select="
                if ($top-level-table) then
                  concat('tbl_', $unique-id,'_fnsrc_', $fn-id)
                else
                  concat('fnsrc_', $fn-id)"/>
            <xsl:attribute name="href" select="
                if ($top-level-table) then
                  concat('#tbl_', $unique-id,'_fntarg_', $fn-id)
                else
                  concat('#fntarg_', $fn-id)"/>
            <sup>
              <xsl:value-of select="$converged-callout"/>
            </sup>
          </a>
        </xsl:if>
      </xsl:template>
    
      <!--
        The xrefs to footnotes with IDs inside table-cells. We need to recalculate
        their indexes if their referenced footnote is also in the table.
      -->
      <xsl:template match="
          *[contains(@class, 'topic/xref')][@type = 'fn']
          [ancestor::*[contains(@class, 'topic/entry')]]">
        <xsl:param name="top-level-table" tunnel="yes"/>
    
        <xsl:variable name="topic-id" select="substring-after(@href, '#')"/>
        <xsl:variable name="element-id" select="substring-after($topic-id, '/')"/>
        <xsl:variable name="destination">
          <xsl:choose>
            <xsl:when test="$element-id = ''">
              <xsl:value-of select="$topic-id"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="$element-id"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>
    
        <xsl:variable name="fn" select="
            $top-level-table//*[contains(@class, 'topic/fn')][@id = $destination]"/>
        <xsl:choose>
          <xsl:when test="$fn">
            <xsl:variable name="unique-id" select="generate-id($top-level-table)"/>
            <!-- There is a reference in the table, recalculate index. -->
            <xsl:variable name="fn-id" select="
                index-of($top-level-table//*[contains(@class, 'topic/fn')], $fn)"/>
            <a name="tbl_{$unique-id}_fnsrc_{$fn-id}" href="#tbl_{$unique-id}_fntarg_{$fn-id}">
              <sup>
                <xsl:value-of select="$fn-id"/>
              </sup>
            </a>
          </xsl:when>
          <xsl:otherwise>
            <!-- There is no reference in the table, keep original index. -->
            <xsl:next-match/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    
      <!--
        Output footnotes below tables and at the end of the topic.
      -->
      <xsl:template match="*[contains(@class, ' topic/fn ')]" mode="genEndnote">
        <!-- Do not process footnotes from tables. -->
        <xsl:if test="not(node()/ancestor::*[contains(@class, 'topic/table')])">
          <div>
            <!-- Do not number footnotes from tables. -->
            <xsl:variable name="fn-id" select="index-of(//*[contains(@class, 'topic/fn')]
              [not(ancestor::*[contains(@class, 'topic/entry')])], .)"/>
            <xsl:variable name="callout" select="@callout"/>
            <xsl:variable name="converged-callout" select="
                if (string-length($callout) > 0) then
                  $callout
                else
                  $fn-id"/>
    
            <xsl:call-template name="commonattributes"/>
            <xsl:choose>
              <xsl:when test="@id and not(@id = '')">
                <xsl:variable name="topic-id" select="
                  ancestor::*[contains(@class, ' topic/topic ')][1]/@id"/>
                <xsl:variable name="ref-id" select="concat($topic-id, '/', @id)"/>
                <xsl:choose>
                  <xsl:when test="key('xref', $ref-id)">
                    <a>
                      <xsl:call-template name="setid"/>
                      <sup>
                        <xsl:value-of select="$converged-callout"/>
                      </sup>
                    </a>
                    <xsl:text>  </xsl:text>
                  </xsl:when>
                  <xsl:otherwise>
                    <sup>
                      <xsl:value-of select="$converged-callout"/>
                    </sup>
                    <xsl:text>  </xsl:text>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:when>
              <xsl:otherwise>
                <a name="fntarg_{$fn-id}" href="#fnsrc_{$fn-id}">
                  <sup>
                    <xsl:value-of select="$converged-callout"/>
                  </sup>
                </a>
                <xsl:text>  </xsl:text>
              </xsl:otherwise>
            </xsl:choose>
    
            <xsl:apply-templates/>
          </div>
        </xsl:if>
      </xsl:template>
    
    </xsl:stylesheet>
  5. Open the template descriptor file associated with your publishing template and set the XSLT stylesheet created in the previous step with the com.oxygenxml.webhelp.xsl.dita2webhelp XSLT extension point.
    <publishing-template>
        ...
        <webhelp>
            ...        
            <xslt>
                <extension 
                file="xslt/tablesFootnotes.xsl" 
                id="com.oxygenxml.webhelp.xsl.dita2webhelp"/>
  6. Open the DITA Map WebHelp Responsive transformation scenario.
  7. Click the Choose Custom Publishing Template link and select your template.
  8. Click OK to save the changes to the transformation scenario.
  9. Run the transformation scenario.