RE: [xsl] current-group()[1] within xsl:for-each-group

Subject: RE: [xsl] current-group()[1] within xsl:for-each-group
From: Kevin Rodgers <kevin.rodgers@xxxxxxx>
Date: Wed, 2 Mar 2005 16:30:14 -0700
Michael Kay writes:
> The nodes within each group should be in "population order", that is,
> the order of the original sequence, which in this case is document
> order.

Hmmm, I'm pretty sure that wasn't holding true.  But it was only for a
fraction of a very large input document, I've fixed the bug that
resulted from my fundamental misunderstanding, and I'm trying to
complete a project, so I'm not inclined to report a possible bug to the
implementor right now.

> I notice that you are doing something a little unusual, you are
> sorting the groups using something other than the grouping key. The
> sort key (for sorting the groups) mb3e:prim_sort_key is evaluated
> against the first item in each group - if its value differs from one
> member of the group to another this could be quite confusing.

Right.  The sort key (mb3e:prim_sort_key) is constant for the examples
I've seen, and I understand that should be true across the board.  But
that key is not the definitive grouping key (mb3e:fam_id), which is just
a machine-generated identifier not useful for sorting.

> The xsl:sort within the apply-templates should affect the order in
> which the items within each group are processed, but it doesn't affect
> the result of current-group() - at least, it shouldn't!

At least in Saxon 8.3, it's clearly conformant! :-)

> > Now if the unintended output had come from applying the matching
> > template to the group's first node (in terms of document order), I
> > would have immediately realized that.  But for some reason the nodes
> > in the group are not in document order.  Why is that?
> As I say, I think they should be in document order as far as
> current-group() is concerned; but not processed in document order,
> because of the xsl:sort within apply-templates.

Things that make you go "Hmmm"...

> > Here is a more concrete question: Would it make a difference
> > semantically or performance-wise if I changed this
> > 
> >       <xsl:for-each-group select="mb3e:document" group-by="mb3e:fam_id">
> > to this
> >       <xsl:for-each-group select="mb3e:document" group-by="text(mb3e:fam_id)">
> > 
> > or is that effectively what is done when the each node's grouping key
> > sequence is atomized and the resulting values compared?
> There's no text() function - you probably meant string() or data() - but
> either way, you're only doing explicitly what the system is doing anyway.

Good, it's nice to guess right once in a while.


> > But again I wonder: Would it make a difference if I changed . (dot) to
> > current():
> > 
> >   <xsl:variable name="structured-number"
> >                 select="if (position() = 1)
> >                         then $family-structured-number
> >                         else esd:structured-number(current())"/>
> No, in this context . and current() are synonyms.

Good.  I just wasn't sure because the XSLT 2.0 spec says

	The current function, used within an XPath expression, returns
	the item that was the context item at the point where the
	expression was invoked from the XSLT stylesheet. This is
	referred to as the current item. For an outermost expression (an
	expression not occurring within another expression), the current
	item is always the same as the context item. Thus,
	<xsl:value-of select="current()"/>
	means the same as
	<xsl:value-of select="."/>
	However, within square brackets, or on the right-hand side of
	the / operator, the current item is generally different from the
	context item.

and even though . is not "within square brackets, or on the right-hand
side of the / operator", it is within if ... then ... else ... which I
thought might qualify as "within another expression".

Thanks again for all your help!  I definitely owe you a beverage of your
choice if I ever get the opportunity.


Current Thread