[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
[Recent Entries]
[Reply To This Message]
Re: xsl:for-each-group help needed !
Thanks a lot, Martin, Gerrit, Dimitre, Graydon ! I now need half a day
to understand all your solutions, translate them to my real data
structure, and choose the clearest one !
Thanks again,
Christophe
Le 17/09/2020 C 00:47, Graydon graydon@xxxxxxxxx a C)critB :
On 16.09.2020 23:19, Christophe Marchand cmarchand@xxxxxxxxxx wrote:
[group the blocks]
Here is a sample input :
<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 id="i7" width="55">content</block>
B B <block id="i8" width="20">content</block>
B B <block id="i9">content</block>
</blocks>
Here is the expected output :
<blocks>
B B <block id="i1">content</block>
B B <block type="composite">
B B B <block id="i2" width="33">content</block>
B B B B <block id="i3" width="67">content</block>
B B </block>
B B <block type="composite">
B B B <block id="i4" width="50">content</block>
B B B B <block id="i5" width="50">content</block>
B B </block>
B B <block type="composite">
B B B <block id="i6" width="25">content</block>
B B B B <block id="i7" width="55">content</block>
B B B <block id="i8" width="20">content</block>
B B </block>
B B <block id="i9">content</block>
</blocks>
I have no idea of which form of for-each-group I have to use...
It's not as short as I hoped, but a two-pass approach can avoid an
accumulator:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="xs math xd" version="3.0"
xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xd:doc scope="stylesheet">
<xd:desc>
<xd:p><xd:b>Created on:</xd:b> Sep 16, 2020</xd:p>
<xd:p><xd:b>Author:</xd:b> graydon</xd:p>
<xd:p />
</xd:desc>
</xd:doc>
<xsl:mode name="numbers" on-no-match="shallow-copy" />
<xsl:mode name="group" on-no-match="shallow-copy" />
<xsl:variable as="element(blocks)" name="input">
<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 id="i7" width="55">content</block>
<block id="i8" width="20">content</block>
<block id="i9">content</block>
</blocks>
</xsl:variable>
<xd:doc>
<xd:desc>main template</xd:desc>
</xd:doc>
<xsl:template name="xsl:initial-template">
<xsl:variable name="pass1">
<xsl:apply-templates mode="numbers" select="$input" />
</xsl:variable>
<xsl:apply-templates mode="group" select="$pass1" />
</xsl:template>
<xd:doc>
<xd:desc>add numbers to the blocks</xd:desc>
</xd:doc>
<xsl:template match="block" mode="numbers">
<xsl:copy>
<xsl:apply-templates mode="numbers" select="@*" />
<xsl:if test="@width">
<xsl:attribute name="count" select="(preceding-sibling::block/@width => sum()) mod 100" />
</xsl:if>
<xsl:apply-templates mode="numbers" select="node()" />
</xsl:copy>
</xsl:template>
<xd:doc>
<xd:desc>do the grouping</xd:desc>
</xd:doc>
<xsl:template match="blocks" mode="group">
<xsl:copy>
<xsl:apply-templates mode="group" select="@*" />
<xsl:for-each-group group-starting-with="block[@count/number() lt preceding-sibling::block[1]/@count/number()]"
select="*">
<xsl:for-each-group group-adjacent="(self::block[exists(@count)], false())[1]" select="current-group()">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<block type="composite">
<xsl:apply-templates mode="group" select="current-group()" />
</block>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates mode="group" select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xd:doc>
<xd:desc>remove count attributes</xd:desc>
</xd:doc>
<xsl:template match="@count" mode="group">
<!-- thud -->
</xsl:template>
</xsl:stylesheet>
produces:
<?xml version="1.0" encoding="UTF-8"?>
<blocks>
<block id="i1">content</block>
<block type="composite">
<block id="i2" width="33">content</block>
<block id="i3" width="67">content</block>
</block>
<block type="composite">
<block id="i4" width="50">content</block>
<block id="i5" width="50">content</block>
</block>
<block type="composite">
<block id="i6" width="25">content</block>
<block id="i7" width="55">content</block>
<block id="i8" width="20">content</block>
</block>
<block id="i9">content</block>
</blocks>
|
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 |
|
|