RE: [xsl] grouping with xsl:for-each-group

Subject: RE: [xsl] grouping with xsl:for-each-group
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Tue, 21 Apr 2009 09:56:58 +0100
Try:

<xsl:for-each-group select="*" group-adjacent="local-name()">
  <xsl:choose>
    <xsl:when test="starts-with(current-grouping-key(), 'einschub')">
      <einschub typ='replace(local-name(), "[^\d]+", "")'>
          <xsl:apply-templates select="current-group()"/>
      </einschub>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="current-group()"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:for-each-group>     

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

> -----Original Message-----
> From: gregor FELLENZ [mailto:gregor@xxxxxxxxxxxx] 
> Sent: 21 April 2009 09:47
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] grouping with xsl:for-each-group
> 
> hi there,
> 
> i've got a flat xml document and need some hierachy in there. 
> the first approach was promising, but now i'm stuck how to 
> fix the last bit.
> i think i could do a procedural style, but i guess theres an 
> elegant solution for the problem.
> 
> i would like to put any group of "einschub" elements in a 
> separate container. this works fine when there's an other 
> element inbetween. but fails with different "einschub" 
> sibling-elements.
> 
> step by step:
> 1. source doc:
> <kapitel>
>      <abs>abs</abs>
>      <einschub1>einschub1</einschub1>
>      <einschub1>einschub1</einschub1>
>      <abs>abs</abs>
>      <einschub1>einschub1</einschub1>
>      <einschub2>einschub2</einschub2>
>      <abs>abs</abs>
>      <abs>abs</abs>
> </kapitel>
> 
> 2. xslt
> <xsl:template match="kapitel">
>      <xsl:element name="kapitel">
>          <xsl:for-each-group select="*" 
> group-adjacent="starts-with(local-name(),'einschub')" >
>              <xsl:choose>
>                  <xsl:when test="current-grouping-key()">
>                      <xsl:element name="einschub">
>                          <xsl:attribute name="typ" 
> select='replace(local-name(), "[^\d]+", "")'/>
>                          <xsl:apply-templates 
> select="current-group()"/>
>                      </xsl:element>
>                  </xsl:when>
>                  <xsl:otherwise>
>                      <xsl:apply-templates select="current-group()"/>
>                  </xsl:otherwise>
>              </xsl:choose>
>          </xsl:for-each-group>
>      </xsl:element>
> </xsl:template>
> 
> <xsl:template match="einschub1|einschub2">
>          <xsl:element name="abs">
>              <xsl:apply-templates/>
>          </xsl:element>
> </xsl:template>
> 
> 3. output with saxon9
> <kapitel>
>      <abs>abs</abs>
>      <einschub typ="1">
>          <abs>einschub1</abs>
>          <abs>einschub1</abs>
>      </einschub>
>      <abs>abs</abs>
>      <einschub typ="1">
>          <abs>einschub1</abs>
>          <abs>einschub2</abs>
>      </einschub>
>      <abs>abs</abs>
>      <abs>abs</abs>
> </kapitel>
> 
> 
> 4. desired output
> <kapitel>
>      <abs>abs</abs>
>      <einschub typ="1">
>          <abs>einschub1</abs>
>          <abs>einschub1</abs>
>      </einschub>
>      <abs>abs</abs>
>      <einschub typ="1">
>          <abs>einschub1</abs>
>      </einschub>
>      <einschub typ="2">
>          <abs>einschub2</abs>
>      </einschub>
>      <abs>abs</abs>
>      <abs>abs</abs>
> </kapitel>
> 
> any help is greatly appreciated!
> 
> 
> all the best,
> gregor

Current Thread