ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: Numbering Figures in a Document
Submitter: Chris Maloney (other recipes)
Last Updated: 2005/05/23
Version no: 1.0
Category: XPath Tricks

 

Not Rated yet


Description:

Sometimes, in a formal document, you want the figures numbered like "2-3", "5-4",
etc., where the first number is the section number, and the second number is the figure number within the section.

Source: Text Source

Given this source document:

<Document>
  <Title>Large Document</Title>
  <p>...</p>

  <Section>
    <Title>Section 1</Title>
    <Figure ref="cocoon-built.gif"/>

    <Section>
      <Title>Section 1.1</Title>
      <Figure ref="cocoon-built.gif"/>
    </Section>

    <Section>
      <Title>Section 1.2</Title>
      <Figure ref="cocoon-built.gif"/>
    </Section>
  </Section>

  <Section>
    <Title>Section 2</Title>
    <Figure ref="cocoon-built.gif"/>
    <Figure ref="cocoon-built.gif"/>
  </Section>
</Document>


And this XSLT:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match='Figure'>

    <!-- Here's the node of the main section in which this Figure resides -->
    <xsl:variable name='myMainSection'
        select='ancestor::Section[last()]'/>

    <!-- Calculate the section number -->
    <xsl:variable name='secNum'>
      <xsl:value-of
          select='count($myMainSection/preceding-sibling::Section) + 1'/>
    </xsl:variable>

    <xsl:variable name='figNum'
        select='count(preceding::Figure[ ancestor::Section[last()] =
                                         $myMainSection ]) + 1'/>

    <xsl:copy>
      <!-- copy all the other attributes of the Figure element -->
      <xsl:for-each select='@*'>
        <xsl:copy/>
      </xsl:for-each>

      <!-- add a num attribute with the calculated value -->
      <xsl:attribute name='num'>
        <xsl:value-of select='concat($secNum, "-", $figNum)'/>
      </xsl:attribute>
    </xsl:copy>
  </xsl:template>

<!--
  Default template causes everything else to be copied.
-->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>


You get this output:

<Document>
  <Title>Large Document</Title>
  <p>...</p>

  <Section>
    <Title>Section 1</Title>
    <Figure ref="cocoon-built.gif" num="1-1"/>

    <Section>
      <Title>Section 1.1</Title>
      <Figure ref="cocoon-built.gif" num="1-2"/>
    </Section>

    <Section>
      <Title>Section 1.2</Title>
      <Figure ref="cocoon-built.gif" num="1-3"/>
    </Section>
  </Section>

  <Section>
    <Title>Section 2</Title>
    <Figure ref="cocoon-built.gif" num="2-1"/>
    <Figure ref="cocoon-built.gif" num="2-2"/>
  </Section>

</Document>


Cool, huh?
Cheers!
Chris Maloney

The license for this recipe is available here.

Discussion:



Add comment

No comments.



Highest rated recipes:

1. Search and Replace

2. Generating a newline

3. Internationalization ...

4. Restricting processing ...

5. Result Pagination with ...

6. Fetching information ...

7. Getting text children of ...

8. Creating empty elements




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.