Re: [xsl] Wrap changing element sequence into container: with 'for-each-group'?

Subject: Re: [xsl] Wrap changing element sequence into container: with 'for-each-group'?
From: Yves Forkl <Y.Forkl@xxxxxx>
Date: Wed, 31 Jan 2007 16:32:06 +0100
David Carlisle schrieb:

It's so much easier if you provide an example, failing that I'll provide
one:-)

I apologize for wasting your time by having you guess what I mean instead of giving an example right away. As was to be expected, my longish explanations would mislead you about what I was looking for... So I shamefully promise to get better - here is a realistic example I was able to craft.


input.xml (I left blank lines to emphasize the variations):

<root>
  <flatsequence>
    <a>a</a>
    <b>b</b>
    <c>c</c>
    <d>d</d>
    <e>e</e>
    <f>f</f>

    <h>h</h>
    <i>i</i>
    <j>j</j>
  </flatsequence>
  <flatsequence>
    <a>a</a>

    <c>c</c>
    <d>d</d>
    <e>e</e>
    <f>f</f>
    <g>g</g>
    <h>h</h>
    <i>i</i>
    <j>j</j>
  </flatsequence>
</root>


desired output:


<root>
  <hierarchy>
    <a>a</a>
    <container1>
      <b>b</b>
      <c>c</c>
    </container1>
    <d>d</d>
    <e>e</e>
    <f>f</f>
    <container2>

      <h>h</h>
      <i>i</i>
    </container2>
    <j>j</j>
  </hierarchy>
  <hierarchy>
    <a>a</a>
    <container1>

      <c>c</c>
    </container1>
    <d>d</d>
    <e>e</e>
    <f>f</f>
    <container2>
      <g>g</g>
      <h>h</h>
      <i>i</i>
    </container2>
    <j>j</j>
  </hierarchy>
</root>


This is, I want to group certain element sequences (of which the first element may be optional) that are occurring within a flat sequence into some container, and group other element sequences within the same flat sequence the same way into other containers, while leaving the rest unchanged. The elements to group, however, are not easily identified formally as their names are dissimilar, so I suppose I will have to spell out their names.


Your last style sheet suggestion was fine. Adapting it to my example lets me create container1 in the case above, but I am stuck as far as creating container2 in the same run is concerned:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output indent="yes"/>

  <xsl:template match="root">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

<xsl:template match="flatsequence">
<hierarchy>
<xsl:for-each-group
select="*" group-adjacent="exists(self::b|self::c)">
<!-- how to match g, h and i as well within the same "for-each-group"? -->
<xsl:choose>
<xsl:when test="current-grouping-key()">
<container1>
<xsl:copy-of select="current-group()"/>
</container1>
</xsl:when>
<!-- how to group g, h and i into container2? -->
<xsl:otherwise>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</hierarchy>
</xsl:template>


</xsl:stylesheet>


How to care, in the same pass, for container2 (and a finite number of other containers), which have no "derivable" relation to the elements they are to group?


Do I have to apply some kind of tree-walking or recursion?

Yves

Current Thread