XSLT copy groups per chunks and keep children nodes

im trying to achieve this:
I have this input file

<Message>
   <Cons>
      <TratEqnt>
         <sqNumberFinal>1</sqNumberFinal>
         <numberOfSls>104</numberOfSls>
         <Sl>
            <sqNumber>1</sqNumber>
            <id>D36831581</id>
         </Sl>
         <Sl>
            <sqNumber>2</sqNumber>
            <id>D36831582</id>
         </Sl>
         <Sl>
            <sqNumber>3</sqNumber>
            <id>D36831583</id>
         </Sl>
         <Sl>
            <sqNumber>4</sqNumber>
            <id>D36831584</id>
         </Sl>
         <Sl>
            <sqNumber>5</sqNumber>
            <id>D36831585</id>
         </Sl>
         <Sl>
            <sqNumber>6</sqNumber>
            <id>D36831586</id>
         </Sl>
         <Sl>
            <sqNumber>7</sqNumber>
            <id>D36831587</id>
         </Sl>
      </TratEqnt>
      <TratEqnt>
         <Sl>
            <sqNumber>1</sqNumber>
            <id>D36831581</id>
         </Sl>
         <Sl>
            <sqNumber>2</sqNumber>
            <id>D36831582</id>
         </Sl>
         <Sl>
            <sqNumber>3</sqNumber>
            <id>D36831583</id>
         </Sl>
         <Sl>
            <sqNumber>4</sqNumber>
            <id>D36831584</id>
         </Sl>
         <Sl>
            <sqNumber>5</sqNumber>
            <id>D36831585</id>
         </Sl>
         <Goods>
            <seq>1</seq>
            <dec>1</dec>
         </Goods>
      </TratEqnt>
   </Cons>
</Message>

and what i want to achieve is that if in every TratEqnt group the number Slis greater than 4 for example 12 then i should create others TratEqnt with chunks of 4 SL until there are no <Sl> left. It is important that each TratEqnt must has the children nodes. To be more specific my output for the given message must be this:

<Message>
   <Cons>
        <TratEqnt>
             <sqNumberFinal>1</sqNumberFinal>
             <numberOfSls>104</numberOfSls>
             <Sl>
                <sqNumber>1</sqNumber>
                <id>D36831581</id>
             </Sl>
             <Sl>
                <sqNumber>2</sqNumber>
                <id>D36831582</id>
             </Sl>
             <Sl>
                <sqNumber>3</sqNumber>
                <id>D36831583</id>
             </Sl>
             <Sl>
                <sqNumber>4</sqNumber>
                <id>D36831584</id>
             </Sl>
         </TratEqnt>
         <TratEqnt>
             <sqNumberFinal>1</sqNumberFinal>
             <numberOfSls>104</numberOfSls>
             <Sl>
                <sqNumber>5</sqNumber>
                <id>D36831585</id>
             </Sl>
             <Sl>
                <sqNumber>6</sqNumber>
                <id>D36831586</id>
             </Sl>
             <Sl>
                <sqNumber>7</sqNumber>
                <id>D36831587</id>
             </Sl>
        </TratEqnt>
        <TratEqnt>
             <Sl>
                <sqNumber>1</sqNumber>
                <id>D36831581</id>
             </Sl>
             <Sl>
                <sqNumber>2</sqNumber>
                <id>D36831582</id>
             </Sl>
             <Sl>
                <sqNumber>3</sqNumber>
                <id>D36831583</id>
             </Sl>
             <Sl>
                <sqNumber>4</sqNumber>
                <id>D36831584</id>
             </Sl>
         </TratEqnt>
         <TratEqnt>
         <Sl>
            <sqNumber>5</sqNumber>
            <id>D36831585</id>
         </Sl>
        </TratEqnt>
   </Cons>
</Message>

My code is this but it is not working properly

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform&quot;
version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema&quot;
exclude-result-prefixes="#all"
expand-text="yes">

<xsl:output method="xml" indent="yes"/>

<xsl:template match="TratEqnt">
    <xsl:copy>
        <xsl:for-each-group select="Sl" group-adjacent="(position() - 1) idiv 4">
          <xsl:copy-of select="current-group()"/>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

>Solution :

It sounds as if you want to change

<xsl:template match="TratEqnt">
    <xsl:copy>
        <xsl:for-each-group select="Sl" group-adjacent="(position() - 1) idiv 4">
          <xsl:copy-of select="current-group()"/>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

to

<xsl:template match="TratEqnt">
    <xsl:copy>
        <xsl:copy-of select="* except Sl"/>
        <xsl:for-each-group select="Sl" group-adjacent="(position() - 1) idiv 4">
          <xsl:copy-of select="current-group()"/>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

or probably rather

<xsl:template match="TratEqnt">
        <xsl:for-each-group select="Sl" group-adjacent="(position() - 1) idiv 4">
           <xsl:copy select="..">
             <xsl:copy-of select="* except Sl"/>

             <xsl:copy-of select="current-group()"/>
           </xsl:copy>
        </xsl:for-each-group>
</xsl:template>

Copying the outer nodes could be done with XSLT 3 by declaring <xsl:mode on-no-match="shallow-copy"/>.

Leave a Reply