This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Grouping and Sorting on value inside group
- From: "Hunsberger, Peter" <Peter dot Hunsberger at stjude dot org>
- To: "'xsl-list at lists dot mulberrytech dot com'" <xsl-list at lists dot mulberrytech dot com>
- Date: Mon, 10 Jun 2002 16:55:51 -0500
- Subject: [xsl] Grouping and Sorting on value inside group
- Reply-to: xsl-list at lists dot mulberrytech dot com
As I've mentioned a couple of times recently I have a problem with keys that
I've been having trouble with. Basically, I have to rotate some data
x | c b a d
y | e _ d _
z | _ h f g
to
x y z
--------
c e _
b _ h
a d f
d _ g
Where there is a common id to group on. Moreover I need to sort the
resultant rows based on a variable that will name a particular column.
Essentially, I have some XML of the form:
<dataset>
<groupa>
<data_x dataid="1">
<value>c</value>
</data>
<data_x dataid="2">
<value>b</value>
</data>
<data_x dataid="3">
<value>a</value>
</data>
<data_x dataid="4">
<value>d</value>
</data>
<data_y dataid="1">
<value>e</value>
</data>
<data_y dataid="2"/>
<data_y dataid="3">
<value>d</value>
</data>
<data_y dataid="4"/>
<data_z dataid="1"/>
<data_z dataid="2">
<value>h</value>
</data>
<data_z dataid="3">
<value>f</value>
</data>
<data_z dataid="4">
<value>g</value>
</data>
</groupa>
</dataset>
This needs to be transformed into:
<groupa>
<data_x dataid="1">
<value>c</value>
</data>
<data_y dataid="1">
<value>e</value>
</data>
<data_z dataid="1"/>
<data_x dataid="2">
<value>b</value>
</data>
<data_y dataid="2"/>
<data_z dataid="2">
<value>h</value>
</data>
<data_x dataid="3">
<value>a</value>
</data>
<data_y dataid="3">
<value>d</value>
</data>
<data_z dataid="3">
<value>f</value>
</data>
<data_x dataid="4">
<value>d</value>
</data>
<data_y dataid="4"/>
<data_z dataid="4">
<value>g</value>
</data>
</groupa>
Where there could be multiple groups, but the "data" elements in each group
are unique. I can do the grouping using:
<xsl:key name="dataids" match="dataset/*/*"
use="concat(local-name(..),@dataId)"/>
and then several templates down:
<xsl:for-each select="//dataset/*/*[generate-id() =
generate-id(key('dataids', concat(local-name(..),@dataId)))]">
but this has the disadvantage of using the // reference to the dataset node.
Is it possible to use an additional(?) key to do this more efficiently?
Since the groups are distinct I believe I don't need to concat with
local-name() but simply "use" @dataid. Does using the local-name help or
hurt?
Next, is it possible to sort this grouping by the text of the value nodes?
Eg; if I get passed a parameter of "data_y" I'd like to sort the "data"
nodes by the ordering of the id's corresponding to the values in the
"data_y" node. In this case:
<groupa>
<data_x dataid="3">
<value>a</value>
</data>
<data_y dataid="3">
<value>d</value>
</data>
<data_z dataid="3">
<value>f</value>
</data>
<data_x dataid="1">
<value>c</value>
</data>
<data_y dataid="1">
<value>e</value>
</data>
<data_z dataid="1"/>
<data_x dataid="2">
<value>b</value>
</data>
<data_y dataid="2"/>
<data_z dataid="2">
<value>h</value>
</data>
<data_x dataid="4">
<value>d</value>
</data>
<data_y dataid="4"/>
<data_z dataid="4">
<value>g</value>
</data>
</groupa>
I'm fine with nodes with no value text child node being sorted first or
last... This can be done as a two stage transformation; the sorting can be
done first or in the same transformation as the grouping, but the grouping
has to be done in the last transformation.
Peter Hunsberger
Phone: 901-495-5252
E-mail: Peter.Hunsberger@stjude.org
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list