|
Subject: Re: [xsl] Grouping and Sorting on value inside group From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Wed, 12 Jun 2002 19:33:57 +0100 |
Hi Peter,
I'm new to the thread, so I'm sorry if this has been mentioned before,
but I think that you can do:
<!-- index the data by local name -->
<xsl:key name="names" match="dataset/*/*" use="local-name()" />
<!-- index the data by id -->
<xsl:key name="ids" match="dataset/*/*" use="@dataid" />
<!-- index the data by name and id -->
<xsl:key name="names-and-ids" match="dataset/*/*/value"
use="concat(local-name(), '+', @dataid)" />
and then:
<!-- $sortcol holds the name of the column to sort by -->
<xsl:variable name="sortcol" select="'data_x'" />
<!-- $data holds the data within the document -->
<xsl:variable name="data" select="//dataset/*/*" />
<!-- $uniqueNames holds the first data elements with particular
names -->
<xsl:variable name="uniqueNames"
select="$data[generate-id() =
generate-id(key('names', local-name())[1])]" />
<!-- iterate over the data elements with unique ids -->
<xsl:for-each
select="$data[generate-id() =
generate-id(key('ids', @dataid)[1])]">
<!-- sort them based on the value of the data element with the
same id and the $sortcol element name -->
<xsl:sort
select="key('ids', @dataid)[local-name() = $sortcol][1]/value" />
<!-- $id holds the current id -->
<xsl:variable name="id" select="@dataid" />
<!-- iterate over the $uniqueNames in alphabetical order -->
<xsl:for-each select="$uniqueNames">
<xsl:sort select="local-name()" />
<!-- create an element of that name -->
<xsl:element name="{local-name()}">
<!-- add a dataid attribute with the id -->
<xsl:attribute name="dataid">
<xsl:value-of select="$id" />
</xsl:attribute>
<!-- copy the value from the source data, if there is one -->
<xsl:copy-of select="key('names-and-ids',
concat(local-name(), '+', $id))" />
</xsl:element>
</xsl:for-each>
</xsl:for-each>
---
In XSLT 2.0, you can do:
<xsl:variable name="sortcol" select="'data_x'" />
<xsl:variable name="data" select="//dataset/*/*" />
<xsl:for-each-group select="$data" group-by="@dataid">
<xsl:sort
select="current-group()[local-name() = $sortcol]/value" />
<xsl:variable name="id" select="@dataid" />
<xsl:variable name="sameID" select="current-group()" />
<xsl:for-each-group select="$data" group-by="local-name()">
<xsl:sort select="local-name()" />
<xsl:element name="{local-name()}">
<xsl:attribute name="dataid">
<xsl:value-of select="$id" />
</xsl:attribute>
<xsl:copy-of
select="$sameID[local-name() =
local-name(current())]/value" />
</xsl:element>
</xsl:for-each-group>
</xsl:for-each-group>
although it would probably be better to create a set of unique names
as above, with something like:
<xsl:variable name="sortcol" select="'data_x'" />
<xsl:variable name="data" select="//dataset/*/*" />
<xsl:variable name="uniqueNames"
select="distinct-values(for $d in $data
return local-name())" />
<xsl:for-each-group select="$data" group-by="@dataid">
<xsl:sort
select="current-group()[local-name() = $sortcol]/value" />
<xsl:variable name="id" select="@dataid" />
<xsl:variable name="sameID" select="current-group()" />
<xsl:for-each select="$uniqueNames">
<xsl:sort select="." />
<xsl:element name="{.}">
<xsl:attribute name="dataid">
<xsl:value-of select="$id" />
</xsl:attribute>
<xsl:copy-of
select="$sameID[local-name() = current()]/value" />
</xsl:element>
</xsl:for-each>
</xsl:for-each-group>
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| [xsl] Grouping and Sorting on value, Hunsberger, Peter | Thread | Re: [xsl] Grouping and Sorting on v, Wendell Piez |
| Re: [xsl] Grouping and Sorting on v, Jeni Tennison | Date | RE: [xsl] Grouping and Sorting on v, Hunsberger, Peter |
| Month |