xsl-list
[Top] [All Lists]

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

2007-09-21 00:51:42
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

--~------------------------------------------------------------------
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>
--~--