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 13:15:19 -0700
Michael Kay writes:
> > I've got this in a template:
> > 
> >       <xsl:for-each-group select="mb3e:document" group-by="mb3e:fam_id">
> >         <xsl:sort select="mb3e:prim_sort_key"/>
> >         <xsl:variable name="first-structured-number"
> >                       select="esd:structured-number(current-group()[1])"/>
> >         <xsl:apply-templates mode="mil" select="current-group()">
> >           <xsl:with-param name="family-structured-number"
> >                           select="$first-structured-number"/>
> >           <xsl:sort select="mb3e:date_list/mb3e:date[@type='PUBL']"
> >                     order="descending"/>
> >         </xsl:apply-templates>
> >       </xsl:for-each-group>
> > 
> > The esd:structured-number function is slow, so I only want to call it
> > once per group.  Actually, the template that is applied within the
> > xsl:for-each-group instruction has to call it for each mb3e:document
> > element, but I want to avoid calling it more than once for 
> > any of those elements (including the first, i.e. most recent):
> I'm not sure what you mean by "the most recent document". current-group()[1]
> selects the first item in the group currently being processed.

This is the crux of the matter.  My mistake was in thinking that
xsl:sort within xsl:apply-templates would somehow affect the order of
the element nodes within the group -- of course it can't.

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?

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?

> >   <xsl:variable name="structured-number"
> >                 select="if (position() = 1)
> >                         then $family-structured-number
> >                         else esd:structured-number(.)"/>
> Where is this variable declared, and where is it used? The reference to
> position() makes it highly context-sensitive. 

As I tried to express, it is declared within the xsl:template that is
applied above (within xsl:for-each-group).  position() seems to work as
I assumed, returning the matched node's position within the group.

But again I wonder: Would it make a difference if I changed . (dot) to

  <xsl:variable name="structured-number"
                select="if (position() = 1)
                        then $family-structured-number
                        else esd:structured-number(current())"/>

Thanks for all your help!
Kevin Rodgers

Current Thread