This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Grouping problem
- From: "Ruggier, Mario" <Mario dot Ruggier at softplumbers dot com>
- To: <xsl-list at lists dot mulberrytech dot com>
- Cc: <joerg dot heinicke at gmx dot de>
- Date: Mon, 22 Jul 2002 18:55:56 +0200
- Subject: [xsl] Grouping problem
- Reply-to: xsl-list at lists dot mulberrytech dot com
Hello,
I had mailed some time ago about this grouping problem,
but my original description of it was too simplistic.
Here's the more complicated version: I would like to
convert the list of <obj> elements (see INPUT below)
to the hierarchical XML (see OUTPUT below).
The XSL that provides a partial solution to this
(from Joerg Heinicke) is also below. I would like to either
generalize this to support sub-branching (as shown by the
output for "fr") or to find another algorithm.
Many thanks!
Mario Ruggier
===================================
INPUT XML (<obj> elements may occur in any order):
<r>
<obj>
<p.array size="1">
<v>en</v>
</p.array>
</obj>
<obj>
<p.array size="1">
<v>it</v>
</p.array>
</obj>
<obj>
<p.array size="1">
<v>fr</v>
</p.array>
</obj>
<obj>
<p.array size="2">
<v>one</v>
<v>en</v>
</p.array>
</obj>
<obj>
<p.array size="2">
<v>uno</v>
<v>it</v>
</p.array>
</obj>
<obj>
<p.array size="2">
<v>un</v>
<v>fr</v>
</p.array>
</obj>
<obj>
<p.array size="3">
<v>two</v>
<v>one</v>
<v>en</v>
</p.array>
</obj>
<obj>
<p.array size="3">
<v>due</v>
<v>uno</v>
<v>it</v>
</p.array>
</obj>
<obj>
<p.array size="3">
<v>deux</v>
<v>un</v>
<v>fr</v>
</p.array>
</obj>
<obj>
<p.array size="3">
<v>doo</v>
<v>un</v>
<v>fr</v>
</p.array>
</obj>
<obj>
<p.array size="4">
<v>trois</v>
<v>doo</v>
<v>un</v>
<v>fr</v>
</p.array>
</obj>
<obj>
<p.array size="4">
<v>3</v>
<v>doo</v>
<v>un</v>
<v>fr</v>
</p.array>
</obj>
</r>
===================================
OUTPUT (order of sibling <obj> elements is not important):
<r>
<obj name="en">
<obj name="one">
<obj name="two"/>
</obj>
</obj>
<obj name="it">
<obj name="uno">
<obj name="due"/>
</obj>
</obj>
<obj name="fr">
<obj name="un">
<obj name="deux" />
<obj name="doo">
<obj name="trois"/>
<obj name="3"/>
</obj>
</obj>
</obj>
</r>
===================================
Partial soloution XSL:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<!-- grouping key -->
<xsl:key name="arrays" match="p.array" use="v[last()]"/>
<xsl:template match="r">
<xsl:copy>
<!-- select unique <p.array>s, grouped by it's language (last <v>) -->
<xsl:apply-templates
select="obj/p.array[count( . |key('arrays',v[last()])[1] ) = 1]"
mode="unique"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p.array" mode="unique">
<!-- sort all <p.array>s with this language -->
<xsl:apply-templates select="key('arrays', v[last()])">
<!-- alternatively select="count(v)" if no @size-attribute -->
<xsl:sort select="@size" order="descending"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="p.array">
<!-- select only the <p.array> of this language with the most entries -->
<xsl:if test="position() = 1">
<!-- begin with the last <v>, the language -->
<xsl:apply-templates select="v[last()]"/>
</xsl:if>
</xsl:template>
<xsl:template match="v">
<obj name="{text()}">
<!-- select the <v> backwards for order 1, 2, 3 and so on -->
<xsl:apply-templates select="preceding-sibling::v[1]"/>
</obj>
</xsl:template>
</xsl:stylesheet>
===================================
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list