[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

RE: [xsl] alphabetic counters


Subject: RE: [xsl] alphabetic counters
From: "Michael Kay" <mhk@xxxxxxxxx>
Date: Mon, 10 May 2004 17:17:20 +0100

> Which is processed by this XSLT fragment:
> 
> <xsl:for-each select="reference">
>    <xsl:text disable-output-escaping="yes"><![CDATA[<a 
> href="#]]></xsl:text><xsl:value-of select="@cite"/><xsl:text 
> disable-output-escaping="yes"><![CDATA[">]]></xsl:text>
>    <xsl:value-of select="id(@cite)/@author" />
>    <xsl:if test="id(@cite)/@year != ''"><xsl:text> 
> </xsl:text><xsl:value-of select="id(@cite)/@year" /></xsl:if>
>    <xsl:text disable-output-escaping="yes"><![CDATA[</a>]]></xsl:text>
>    <xsl:if test="position() != last()"><xsl:text>, 
> </xsl:text></xsl:if>
> </xsl:for-each>

First thing is to tidy up this garbage. This code is trying to produce
serialized HTML as output, bypassing the creating of a result tree. This is
like escaping into assembly language when writing Java - it's unmaintainable
and totally unecessary. You want:

<xsl:for-each select="reference">
   <a href="#{@cite}"/>
    <xsl:value-of select="id(@cite)/@author" />
    <xsl:if test="id(@cite)/@year != ''">
       <xsl:value-of select="id(@cite)/@year" />
    </xsl:if>
   </a>
   <xsl:if test="position() != last()">,&#xa;</xsl:if> 
</xsl:for-each>

> 
> What my problem is, is that references like the above are supposed to 
> be suffixed by a lower case alphabetic character ('a', 'b', 
> etc.) after 
> the year if there are multiple 'citation' elements with identical 
> values for 'author' and 'year'. I have no idea how to go about doing 
> this. Can anyone suggest how to do this?

First define a key:

<xsl:key name="k" match="citation" use="concat(@author, '/', @year)"/>

To find all the citations for a given author and year:

<xsl:variable name="group" select="key('k', concat($author, '/', $year))"/>

To find the position of a given citation $id in this list:

<xsl:variable name="p">
  <xsl:for-each select="key('k', concat($author, '/', $year))">
    <xsl:if test="@id = $id"><xsl:value-of select="position()"/></xsl:if>
  </xsl:for-each>
</xsl:variable>

To add your suffix:

<xsl:variable name="suffix"
    select="substring('abcdefghijklm', $p - 1, 1)"/>

In XSLT 2.0 you can do:

<xsl:variable name="suffix"
  select="substring('abcdefghijklm', 
                    count(key('k', @author, '/', @year))[.<<current()] - 1,
1)"/>
                
Not tested (and requires finishing)

Michael Kay


Current Thread
Keywords