0

I found a lot of grouping questions and they almost got me the wanted result. However, with these it was usually the case that the nodes to be grouped were already listed under a separate group node, so that the apply-templates could target exactly this parent node. I have the following Input XML:

<ROOT>
    <ARTICLE>
        <IMAGE name="demo.jpg" />
        <TABLE>
            <TABLETHEAD>
                Name1
            </TABLETHEAD>
            <TABLEROW>
                <TABLETH>
                    Some Text
                </TABLETH>
                <TABLETD>
                    Some more Text
                </TABLETD>
            </TABLEROW>
        </TABLE>
        <TABLE>
            <TABLETHEAD>
                Name1
            </TABLETHEAD>
            <TABLEROW>
                <TABLETH>
                    Demo Text
                </TABLETH>
                <TABLETD>
                    More Demo Text
                </TABLETD>
            </TABLEROW>
            <TABLEROW>
                <TABLETH>
                    Even more Text
                </TABLETH>
                <TABLETD>
                    Text
                </TABLETD>
            </TABLEROW>
        </TABLE>
        <GRAPHIC name="demo-graphic.eps" />
    </ARTICLE>
</ROOT>

And this is the desired output:

<ROOT>
    <ARTICLE>
        <IMAGE name="demo.jpg" />
        <TABLE>
            <TABLETHEAD>
                Name1
            </TABLETHEAD>
            <TABLEROW>
                <TABLETH>
                    Some Text
                </TABLETH>
                <TABLETD>
                    Some more Text
                </TABLETD>
            </TABLEROW>
            <TABLEROW>
                <TABLETH>
                    Demo Text
                </TABLETH>
                <TABLETD>
                    More Demo Text
                </TABLETD>
            </TABLEROW>
            <TABLEROW>
                <TABLETH>
                    Even more Text
                </TABLETH>
                <TABLETD>
                    Text
                </TABLETD>
            </TABLEROW>
        </TABLE>
        <GRAPHIC name="demo-graphic.eps" />
    </ARTICLE>
</ROOT>

The tables should be grouped by the same text in TABLETHEAD and the TABLEROWs should be added in each case, so that for each different TABLETHEAD text there is a single table with the TABLEROWs of all the tables belonging to the group.

The important thing is that the sibling nodes (e.g. IMG, GRAPHIC, and many more) remain and the whole order does not change. This is exactly my problem:

If my TABLEs were listed under a common parent node e.g. "TABLES", I could get on with a simple grouping similar to Applying Muenchian grouping for a simple XML with XSLT. So I either lose the sibling nodes or change the order.

I am using xslt 2.0.

LHark
  • 3
  • 3
  • Well, if you use XSLT 2 you don't need Muenchian grouping, you have `xsl:for-each-group` with both `group-by` for your `TABLE`s and `group-adjacent` to preserve the other items or the order in general. It is not clear which result you would want for e.g. `
    t1..
    t1..
    `. Start with the samples in https://stackoverflow.com/tags/xslt-grouping/info
    – Martin Honnen Jan 17 '23 at 17:10

1 Answers1

0

With the help of Martin's comment (thanks a lot!) I came up with combining group-by and group-adjacent:

<xsl:template match="ARTICLE">
    <xsl:copy>
        <xsl:apply-templates select="@*" />
        <xsl:for-each-group select="node()" group-adjacent="string(self::TABLE/TABLETHEAD)">
            <xsl:for-each-group select="current-group()" group-by="string(self::TABLE/TABLETHEAD)">
                <xsl:choose>
                    <xsl:when test="self::TABLE">
                        <TABLE>
                            <xsl:apply-templates select="current-group()[1]/@* | current-group()[1]/TABLETHEAD[1] | current-group()/TABLEROW" />
                        </TABLE>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()" />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

This worked for me.

LHark
  • 3
  • 3