Subject: Re: [xsl] xsl:for-each-group help needed ! From: "Christophe Marchand cmarchand@xxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Thu, 17 Sep 2020 14:53:51 -0000 |
Hi Martin,
Does your code handle this input?
<blocks> B <block id="i1">content</block> B <block id="i2" width="33">content</block> B <block id="i3" width="67">content</block> B <block id="i4" width="50">content</block> B <block id="i5" width="50">content</block> B <block id="i6" width="25">content</block> B <block id="i6a" width="80">content</block> B <block>content</block> B <block id="i7" width="55">content</block> B <block id="i8" width="20">content</block> B <block id="i9">content</block> </blocks>
i6 and i6a, taken together, have a width of 105. I guess then i6a needs to be on a new line.
I introduced an accumulator that can have two values:
<xsl:accumulator name="width" as="xs:integer+" initial-value="0"> B <xsl:accumulator-rule match="blocks" select="0"/> B <xsl:accumulator-rule match="block" B B B select="let $line-width-so-far := $value[1], B B B B B B B B B B B B B B B $current-width := xs:integer((@width, 100)[1]), B B B B B B B B B B B B B B B $would-be-line-width := $line-width-so-far B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B + $current-width B B B B B B B B B B B B B B B return ( B B B B B B B B B B B B B B B B B if ($would-be-line-width gt 100) B B B B B B B B B B B B B B B B B B B then $current-width B B B B B B B B B B B B B B B B B B B else (), B B B B B B B B B B B B B B B B B $would-be-line-width B B B B B B B B B B B B B B B )"/> </xsl:accumulator>
If the line becomes too long, the width of the current block will be prepended to the would-be line length in the accumulator. So then there is a sequence of "line length if line wrap happened before current block" and "line length if line wrap did not happen before current block".
If, on the other hand, the would-be line length is less than or equal to 100, only a single value (the would-be line length) will go into the accumulator.
I added its accumulator value(s) to each block:
<blocks> B B <block id="i1" width="100" acc="100">content</block> B B <block type="composite"> B B B B B <block id="i2" width="33" acc="33 133">content</block> B B B B B <block id="i3" width="67" acc="100">content</block> B B </block> B B <block type="composite"> B B B B B <block id="i4" width="50" acc="50 150">content</block> B B B B B <block id="i5" width="50" acc="100">content</block> B B </block> B B <block id="i6" width="25" acc="25 125">content</block> B B <block id="i6a" width="80" acc="80 105">content</block> B B <block width="100" acc="100 180">content</block> B B <block type="composite"> B B B B B <block id="i7" width="55" acc="55 155">content</block> B B B B B <block id="i8" width="20" acc="75">content</block> B B </block> B B <block id="i9" width="100" acc="100 175">content</block> </blocks>
This has been achieved with a single grouping:
<xsl:template match="blocks"> B <xsl:copy> B B B <xsl:for-each-group select="block" group-starting-with="block[accumulator-before('width')[last()] gt 100]"> B B B B B <xsl:choose> B B B B B B B <xsl:when test="count(current-group()) eq 1"> B B B B B B B B B <xsl:apply-templates select="current-group()"/> B B B B B B B </xsl:when> B B B B B B B <xsl:otherwise> B B B B B B B B B <block type="composite"> 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 </block> B B B B B B B </xsl:otherwise> B B B B B </xsl:choose> B B B </xsl:for-each-group> B </xsl:copy> </xsl:template>
Gerrit
On 17.09.2020 00:16, Martin Honnen martin.honnen@xxxxxx wrote:
I was wondering what output is wanted for
<blocks> B B <block id="i1">content</block> B B <block id="i2" width="33">content</block> B B <block id="i3" width="67">content</block> B B <block id="i4" width="50">content</block> B B <block id="i5" width="50">content</block> B B <block id="i6" width="25">content</block> B B <block>content</block> B B <block id="i7" width="55">content</block> B B <block id="i8" width="20">content</block> B B <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
B B <xsl:template match="blocks"> B B B B <xsl:copy> B B B B B B <xsl:for-each-group select="block" group-adjacent="not(@width)"> B B B B B B B B <xsl:choose> B B B B B B B B B B <xsl:when test="current-grouping-key()"> 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 </xsl:when> B B B B B B B B B B <xsl:otherwise> B B B B B B B B B B B B <xsl:for-each-group select="current-group()" group-ending-with="block[accumulator-before('width') eq 100]"> B B B B B B B B B B B B B B <xsl:choose> B B B B B B B B B B B B B B B B <xsl:when test="current-group()[last()][accumulator-before('width') eq 100]"> B B B B B B B 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 B B B B B B B <xsl:apply-templates select="current-group()"/> B B B B B B B B B B B B B B B B B B </block> B B B B B B B B B B B B B B B B </xsl:when> B B B B B B B B B B B B B B B B <xsl:otherwise> B B B B B 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 B B B B B </xsl:otherwise> B B B B B B B B B B B B B B </xsl:choose> B B B B B B B B B B B B </xsl:for-each-group> B B B B B B B B B B </xsl:otherwise> B B B B B B B B </xsl:choose> B B B B B B </xsl:for-each-group> B B B B </xsl:copy> B B </xsl:template>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] xsl:for-each-group help n, Imsieke, Gerrit, le- | Thread | Re: [xsl] xsl:for-each-group help n, Martin Honnen martin |
Re: [xsl] xsl:for-each-group help n, Imsieke, Gerrit, le- | Date | Re: [xsl] xsl:for-each-group help n, Martin Honnen martin |
Month |