[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
[Recent Entries]
[Reply To This Message]
Re: xsl:for-each-group help needed !
My goal wasn't to start a competition between best XSL coders ! I do not
have enough prices for awards !
But, indeed, this use case may occurs. But I've decided to let the
writer correct what he has done by hand.
To be honest, our editor can not generate such things... but writers may
modify generated files, and try to change width values...
Thanks again, based on Gerrit solution, I have now something that
correctly works.
Le 17/09/2020 C 16:26, Imsieke, Gerrit, le-tex gerrit.imsieke@xxxxxxxxx
a C)critB :
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>
|
PURCHASE STYLUS STUDIO ONLINE TODAY!
Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!
Download The World's Best XML IDE!
Accelerate XML development with our award-winning XML IDE - Download a free trial today!
Subscribe in XML format
RSS 2.0 |
|
Atom 0.3 |
|
|