I think that when you need to do two levels of grouping like this, it is
usually easier to do it top-down: that is, do the outer level first. Doing
it bottom-up as you are attempting also works, but it requires two passes
over the data.
The top-down solution (untested) looks something like this:
<xsl:for-each-group select="bar" group-adjacent="exists(@baz)">
<xsl:choose>
<xsl:when test="exists(@baz)">
<list>
<xsl:for-each-group select="current-group() group-adjacent="@baz">
<list-item>
<xsl:copy-of select="current-group()" />
</list-item>
</xsl:for-each-group>
</list>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
-----Original Message-----
From: A. Pagaltzis [mailto:pagaltzis(_at_)gmx(_dot_)de]
Sent: 24 May 2004 22:52
To: XSLT-List
Subject: [xsl] XSLT2: Clustering, or Grouping the groups
Hi all,
I am using XSLT2 as implemented by Saxon 7.9.1 to group a flat
structure. What I start out with is something like
<foo>
<bar baz="1" />
<bar baz="2" />
<bar baz="2" />
<bar />
<bar baz="1" />
<bar baz="1" />
<bar />
</foo>
Now I need to put these bars in a list. The first step is easy
enough (I'm only paraphrasing; excuse any syntax errors please):
<xsl:for-each-group select="bar" group-adjacent="@baz">
<xsl:choose>
<xsl:when test="@baz">
<list-item>
<xsl:copy-of select="current-group()" />
</list-item>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
Now what I get looks like this:
<foo>
<list-item>
<bar baz="1" />
</list-item>
<list-item>
<bar baz="2" />
<bar baz="2" />
</list-item>
<bar />
<list-item>
<bar baz="1" />
<bar baz="1" />
</list-item>
<bar />
</foo>
This is all well and good, but now I need to get to
<foo>
<list>
<list-item>
<bar baz="1" />
</list-item>
<list-item>
<bar baz="2" />
<bar baz="2" />
</list-item>
</list>
<bar />
<list>
<list-item>
<bar baz="1" />
<bar baz="1" />
</list-item>
</list>
<bar />
</foo>
The only way I've succeeded in doing this was by two separate
stylesheets (where the second is pretty much a copy of the first,
except for different conditions and element names), which is
suboptimal.
I'd like to do this in a single step. I tried assigning the
output to a variable and processing it afterwards using something
like
<xsl:variable name="list">
<xsl:for-each-group select="bar" group-adjacent="@baz">
<xsl:choose>
<xsl:when test="@baz">
<list-item>
<xsl:copy-of select="current-group()" />
</list-item>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:variable>
<xsl:for-each-group select="$list"
Your mistake here is that $list is a document node at the root of a
temporary tree: it is a sequence of length one, so using it as the grouping
population is not going to do much good. You should either select the
children of $list (which will include <list-item> and <baz> elements), or
you should declare the variable as a sequence of elements, by writing
<xsl:variable name="list" as="element()*">, in which case the document node
will not be constructed.
Michael Kay
group-adjacent="boolean(self::list-item)">
<xsl:choose>
<xsl:when test=" SOME-TEST-HERE() "> <!-- KEY BIT -->
<list-item>
<xsl:copy-of select="current-group()" />
</list-item>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
Unfortunately, both what the context node is as well as the value
of current-group() at the point of SOME-TEST-HERE() seem to defy
all reason or reasonable expectation in such a way that I can't
figure out how to get the desired result.
Uh.. help?
--
Thanks muchly in advance,
Aristotle
"If you can't laugh at yourself, you don't take life
seriously enough."
--+------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail:
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--+--