This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
RE: breaking sorted material into subsections
- To: xsl-list at mulberrytech dot com
- Subject: RE: breaking sorted material into subsections
- From: Oliver Becker <obecker at informatik dot hu-berlin dot de>
- Date: Mon, 18 Sep 2000 17:01:50 +0200 (MET DST)
- Reply-To: xsl-list at mulberrytech dot com
Hi Don,
> Assuming XML looks something like this (@location left out because question
> didn't pertain to parent's @location href):
>
>
> <IndexEntryData>
> <index entry = "Ca">Index1</index>
> <index entry = "Aaaa">Index1</index>
> <index entry = "Az">Index1</index>
> <index entry = "Bz">Index1</index>
> <index entry = "Abb">Index1</index>
> <index entry = "Ba">Index1</index>
> </IndexEntryData>
>
> This works in MSXML3 and SAXON
Do you have a different version of Saxon from mine (which is Saxon 5.4.1)?
> <xsl:template match="/">
> <xsl:for-each select="//index">
> <xsl:sort select="@entry"/>
>
> <!-- if first character of @entry attrib of first preceding -->
> <!-- node is not equal to the context's @entry attrib -->
> <!-- it's a "break" on first character of @entry -->
> <!-- this works because we're already sorted by @entry -->
>
> <xsl:if test ="substring(preceding::*[1]/@entry, 1, 1) !=
> substring(@entry, 1, 1)">
All axes apply to the nodes in the document, not to a selected node-set.
That means, your test checks if the entry attribute of the preceding
element in the *document* starts with a different letter.
> <H2><xsl:value-of select="substring(@entry, 1, 1)" /></H2>
> </xsl:if>
>
> <p>
> <a href="{../@location}">
> <xsl:value-of select="@entry"/>
> </a>
> </p>
> </xsl:for-each>
> </xsl:template>
As a result Saxon outputs (newlines added)
<H2>A</H2>
<p><a href="">Aaaa</a></p>
<H2>A</H2>
<p><a href="">Abb</a></p>
<p><a href="">Az</a></p>
<H2>B</H2>
<p><a href="">Ba</a></p>
<H2>B</H2>
<p><a href="">Bz</a></p>
<H2>C</H2>
<p><a href="">Ca</a></p>
i.e. two A headers and two B headers.
In fact it's a grouping problem: gather all indizes starting with the
same letter.
Always a good reading for this kind of problems is
http://www.jenitennison.com/xslt/grouping/muenchian.html
Adapted to Eric's problem I get
<xsl:key name="letters" match="index" use="substring(@entry,1,1)" />
<xsl:template match="IndexEntryData">
<xsl:for-each
select="index[count(. | key('letters',
substring(@entry,1,1))[1]) = 1]">
<xsl:sort select="@entry" />
<xsl:variable name="initial" select="substring(@entry,1,1)" />
<h2> <xsl:value-of select="$initial" /> </h2>
<xsl:for-each select="key('letters', $initial)">
<xsl:sort select="@entry" />
<p> <xsl:value-of select="@entry" /> </p>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
Cheers,
Oliver
/-------------------------------------------------------------------\
| ob|do Dipl.Inf. Oliver Becker |
| --+-- E-Mail: obecker@informatik.hu-berlin.de |
| op|qo WWW: http://www.informatik.hu-berlin.de/~obecker |
\-------------------------------------------------------------------/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list