Subject: Re: [xsl] xsl:for-each-group help needed ! From: "Christophe Marchand cmarchand@xxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Thu, 17 Sep 2020 06:18:11 -0000 |
Thanks again, Christophe
[group the blocks]On 16.09.2020 23:19, Christophe Marchand cmarchand@xxxxxxxxxx wrote: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>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] xsl:for-each-group help n, Graydon graydon@xxxx | Thread | Re: [xsl] xsl:for-each-group help n, Dimitre Novatchev dn |
Re: [xsl] xsl:for-each-group help n, Graydon graydon@xxxx | Date | Re: [xsl] xsl:for-each-group help n, Imsieke, Gerrit, le- |
Month |