Re: "sorted" axis (was: Remove duplicates from a node-set accordi ng to content)

Subject: Re: "sorted" axis (was: Remove duplicates from a node-set accordi ng to content)
From: David Carlisle <davidc@xxxxxxxxx>
Date: Fri, 30 Jul 1999 14:19:33 +0100 (BST)
I said:

> once the nodes are in sorted order, it is easy enough to put
> containing elements around consecutive groups, and to do running totals
> etc. (actually grabbing consecutive things into a containing group may
> not be completely obvious, but it isn't hard, and one would hope that
> over time the archive of useful named templates could be built up to do
> this sort of thing, rather than having to keep extending the language)


for example to convert

<doc>

<element name="a" value="1" />
<element name="a" value="2" />
<element name="a" value="3" />
<element name="a" value="2" />
<element name="b" value="1" />
<element name="b" value="1" />
<element name="b" value="3" />
<element name="b" value="4" />
<element name="a" value="2" />
<element name="a" value="3" />
<element name="a" value="6" />
<element name="a" value="2" />
<element name="c" value="1" />
<element name="c" value="4" />
<element name="c" value="2" />
<element name="c" value="1" />

</doc>

by grabing consecutive runs of the same @name into a containing section
element, and adding a total for each section, to produce:

<section>
<element name="a" value="1"/>
<element name="a" value="2"/>
<element name="a" value="3"/>
<element name="a" value="2"/>
<total>8</total>
</section>
<section>
<element name="b" value="1"/>
<element name="b" value="1"/>
<element name="b" value="3"/>
<element name="b" value="4"/>
<total>9</total>
</section>
<section>
<element name="a" value="2"/>
<element name="a" value="3"/>
<element name="a" value="6"/>
<element name="a" value="2"/>
<total>13</total>
</section>
<section>
<element name="c" value="1"/>
<element name="c" value="4"/>
<element name="c" value="2"/>
<element name="c" value="1"/>
<total>8</total>
</section>

You could do


<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/XSL/Transform/1.0";
  indent-result="yes">


<xsl:template match="doc">
  <xsl:apply-templates mode="sec" select="*[1]"/>
</xsl:template>


<xsl:template mode="sec" match="*">
<xsl:variable name="n" select="@name"/>
<section>
<xsl:apply-templates mode="elem" select="."/>
</section>
<xsl:apply-templates mode="sec" select="following-sibling::*[not(@name=$n)][1]"/>
</xsl:template>


<xsl:template mode="elem" match="*">
<xsl:variable name="n" select="@name"/>
<xsl:param name="t" select="0"/>
<xsl:copy-of select="."/>
<xsl:apply-templates 
   mode="elem"
  select="following-sibling::*[position()=1 and (@name=$n)]">
  <xsl:with-param name="t" select="$t+@value"/>
</xsl:apply-templates>
<xsl:if test="not(following-sibling::*[position()=1 and (@name=$n)])">
<total>
<xsl:value-of select="$t+@value"/>
</total>
</xsl:if>
</xsl:template>


</xsl:stylesheet>



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread