[xsl] Apply for-each-group to a node subset

Subject: [xsl] Apply for-each-group to a node subset
From: Raman Gupta <rocketraman@xxxxxxxxxxx>
Date: Fri, 21 Sep 2007 03:51:13 -0400
Using XSLT2, Saxon 8.7.3.

I want to apply a for-each-group to a node subset, with the rest of
the nodes going through other transformations.

I need to select the containing node, and call for-each-group on the
relevant group nodes, and apply-templates on the nodes before and
after the grouped nodes. Here is the input:

<r>
  <n1/>
  <n2/>

  <!-- groups start -->
  <g1/>
  <g2/>

  <g1/>
  <g2/>
  <!-- groups end -->

  <n3/>
  <n4/>
</r>

Also note that there may be an arbitrary set of elements between g1
and g2, before the groups start, and after the groups end.

The following works, but is there an easier way to do this?

<xsl:template match="r">
  <xsl:copy>
    <!-- process nodes before group -->
    <xsl:apply-templates select="*[following-sibling::g1
        and not(preceding-sibling::g1 or self::g1)]"/>

    <!-- process group -->
    <xsl:for-each-group select="*[(self::g1 or preceding-sibling::g1)

        and (following-sibling::g2 or self::g2)]"
        group-starting-with="g1">
      <g>
        <xsl:apply-templates select="current-group()"/>
      </g>
    </xsl:for-each-group>

    <!-- process nodes after group -->
    <xsl:apply-templates select="*[preceding-sibling::g2
        and not(following-sibling::g2 or self::g2)]"/>
  </xsl:copy>
</xsl:template>

I tried to simplify some of the expressions by using nested predicates
but for some reason that didn't work e.g.

    <!-- process nodes after group -->
    <xsl:apply-templates select="*[preceding-sibling::g2[last()]]"/>

Thanks,
Raman Gupta

Current Thread