RE: [xsl] unusual grouping problem

Subject: RE: [xsl] unusual grouping problem
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Sun, 16 Sep 2007 22:27:51 +0100
I would do this using sibling recursion.

<xsl:template name="group">
  <xsl:param name="seq" as="element(lab)*"/>
  <xsl:param name="current-group" as="element(lab)*"/>
  <xsl:choose>
    <xsl:when test="empty($seq)">
      <group>
        <xsl:copy-of select="$current-group"/>
      </group>
    </xsl:when>
    <xsl:when test="$current-group/@type = ./@type">
      <group>
        <xsl:copy-of select="$current-group"/>
      </group>
      <xsl:call-template name="group">
        <xsl:with-param name="seq" select="remove($seq, 1)"/>
        <xsl:with-param name="current-group" select="."/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
        <xsl:call-template name="group">
            <xsl:with-param name="seq" select="remove($seq, 1)"/>
            <xsl:with-param name="current-group" select="($current-group,
.)"/>
        </xsl:call-template>
    </
  </
</

<xsl:template match="/"
        <xsl:call-template name="group">
            <xsl:with-param name="seq" select="/patient/lab"/>
            <xsl:with-param name="current-group" select="()"/>
        </xsl:call-template>
</

Untested.

Michael Kay
http://www.saxonica.com/
 

> -----Original Message-----
> From: russ@xxxxxxxxxxx [mailto:russ@xxxxxxxxxxx] 
> Sent: 16 September 2007 21:57
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] unusual grouping problem
> 
> I have what I hope is an interesting grouping problem. I've 
> tried <for-each-group>, Meunchian technique, and some crazy 
> home-made <for-each> loops but can't come up with anything that works.
> 
> Source xml is:
> <patient>
> 	<lab type="1" />
> 	<lab type="2" />
> 	<lab type="3" />
> 	<lab type="1" />
> 	<lab type="3" />
> 	<lab type="1" />
> 	<lab type="1" />
> 	<lab type="2" />
> 	<lab type="3" />
> 	<lab type="3" />
> 	<lab type="1" />
> <patient>
> 
> 
> 
> The labs are sorted by a timestamp that I've left out for 
> clarity, and need to remain in that same order.
> 
> I need the labs broken into the fewest number of groups 
> possible without any group containing the same lab type more 
> than once. So the above should
> produce:
> 
> <patient>
> 	<group>
> 		<lab type="1" />
> 		<lab type="2" />
> 		<lab type="3" />
> 	</group>
> 	<group>
> 		<lab type="1" />
> 		<lab type="3" >
> 	</group>
> 	<group>
> 		<lab type="1" />
> 	</group>
> 	<group>
> 		<lab type="1" />
> 		<lab type="2" />
> 		<lab type="3" />
> 	</group>
> 	<group>
> 		<lab type="3"/>
> 		<lab type="1"/>
> 	</group>
> </patient>
> 
> 
> 
> I'd like to do something like :
> <xsl:for-each-group select="/patient/lab " 
> group-adjacent="every $lab in
> current-group() satisfies $lab/@type!=@type">
> 
> but you can't access current-group()  from the grouping 
> criteria. I need something like a 
> "members-of-the-group-currently-being-created()"
> function.  I also tried:
> <xsl:for-each-group select="/patient/lab " 
> group-ending-with="some $lab in preceding-sibling::lab 
> satisfies $lab/@type=@type">
> 
> But that identifies duplicates starting from the first lab in 
> the entire list, not just within the group currently being created.
> 
> 
> I've also tried some more convoluted and desperate ideas but 
> I'll save you those details.
> 
> Any help is much appreciated.
> 
> Thanks.

Current Thread