Search code examples
xmlxsltxslt-2.0

XSLT grouping via for-each-group and group-starting-with?


I'm trying to create group for below example. Element 'ques' and just following-sibling::p make inside the 'group' element
Input XML

<root>
<title>Title</title>
<p>para</p>
<ques>Ques</ques>
<p>aaaa</p>
<fig>aaa</fig>
<box>box</box>
<ques>Ques</ques>
<p>aaaa</p>
<p>bbbb</p>
</root>

XSLT Code:

<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>

<xsl:template match="root">
    <xsl:copy>
        <xsl:for-each-group select="*" group-starting-with="ques">
            <group>
                <xsl:copy-of select="current-group()"/>
            </group>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

Expected Output:

<root>
  <title>Title</title>
  <p>para</p>
  <group>
    <ques>Ques</ques>
    <p>para</p>
  </group>
  <fig>fig</fig>
  <box>box</box>
  <group>
    <ques>Ques</ques>
    <p>para</p>
    <p>para</p>
  </group>
</root>

Link: https://xsltfiddle.liberty-development.net/6qVQdo6


Solution

  • Try perhaps something like:

    XSLT 2.0

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/root">
        <xsl:copy>
            <xsl:for-each-group select="*" group-starting-with="ques">
                <xsl:for-each-group select="current-group()" group-adjacent="self::ques or self::p">    
                    <xsl:choose>
                        <xsl:when test="self::ques">
                            <group>
                                <xsl:copy-of select="current-group()"/>
                            </group>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:copy-of select="current-group()"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each-group>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
      
    </xsl:stylesheet>