Re: [xsl] xsl:for-each-group help needed !

Subject: Re: [xsl] xsl:for-each-group help needed !
From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 16 Sep 2020 22:15:59 -0000
On 17.09.2020 00:09, Imsieke, Gerrit, le-tex gerrit.imsieke@xxxxxxxxx wrote:
With a single for-each-group:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 B  xmlns:xs="http://www.w3.org/2001/XMLSchema";
 B  exclude-result-prefixes="xs" version="3.0">

 B  <xsl:mode default-mode="#unnamed"
 B B B B B B B B B B B  use-accumulators="width"
 B B B B B B B B B B B  on-no-match="shallow-copy"/>

 B  <xsl:accumulator name="width" as="xs:integer" initial-value="0">
 B B B  <xsl:accumulator-rule match="blocks" select="0"/>
 B B B  <xsl:accumulator-rule match="block[not(@width)]" select="100"/>
 B B B  <xsl:accumulator-rule match="block[@width]"
 B B B B B  select="if ($value eq 100)
 B B B B B B B B B B B B B  then xs:integer(@width)
 B B B B B B B B B B B B B  else $value + xs:integer(@width)"/>
 B  </xsl:accumulator>

 B  <xsl:template match="blocks">
 B B B  <xsl:copy>
 B B B B B  <xsl:for-each-group select="block"
 B B B B B B B  group-ending-with="block[accumulator-before('width') eq
100]">
 B B B B B B B  <xsl:choose>
 B B B B B B B B B  <xsl:when test="count(current-group()) eq 1">
 B B B B B B B B B B B  <xsl:apply-templates select="current-group()"/>
 B B B B B B B B B  </xsl:when>
 B B B B B B B B B  <xsl:otherwise>
 B B B B B B B B B B B  <block type="composite">
 B B B B B B B B B B B B B  <xsl:apply-templates select="current-group()"/>
 B B B B B B B B B B B  </block>
 B B B B B B B B B  </xsl:otherwise>
 B B B B B B B  </xsl:choose>
 B B B B B  </xsl:for-each-group>
 B B B  </xsl:copy>
 B  </xsl:template>

</xsl:stylesheet>

I was wondering what output is wanted for


<blocks>
  <block id="i1">content</block>
  <block id="i2" width="33">content</block>
  <block id="i3" width="67">content</block>
  <block id="i4" width="50">content</block>
  <block id="i5" width="50">content</block>
  <block id="i6" width="25">content</block>
  <block>content</block>
  <block id="i7" width="55">content</block>
  <block id="i8" width="20">content</block>
  <block id="i9">content</block>
</blocks>

Neither my suggestion nor the above seem to only wrap the adjacent
block[@width] where the accumulator gives 100.

I complicated or strengthened my attempt as

  <xsl:template match="blocks">
    <xsl:copy>
      <xsl:for-each-group select="block" group-adjacent="not(@width)">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <xsl:apply-templates select="current-group()"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:for-each-group select="current-group()"
group-ending-with="block[accumulator-before('width') eq 100]">
              <xsl:choose>
                <xsl:when
test="current-group()[last()][accumulator-before('width') eq 100]">
                  <block type="composite">
                    <xsl:apply-templates select="current-group()"/>
                  </block>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:for-each-group>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

Current Thread