Search code examples
xsltconcatenation

XSLT Concatenation from different nodes when a string is found


I want to concatenate different nodes from "Time" until there is another data provided in "Sum". Most of the sum nodes are empty. I will like to concatenate the all nodes before the next SUM value to a single reference field.

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <!-- recursive named template -->
        <xsl:template name="hm">
            <xsl:param name="amount"/>
            <xsl:param name="pos"/>
            <xsl:for-each select="../row">
                <xsl:if test="$amount = Sum and $pos = position()"></xsl:if>
                <xsl:choose>
                    <xsl:when test="string-length(Sum) &gt; 0">
                        <xsl:value-of select="Time"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="', '"/>
                        <xsl:value-of select="Time"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </xsl:template>
                            <Reference>
                                <xsl:call-template name="hm">
                                    <xsl:with-param name="amount" select="Sum"/>
                                    <xsl:with-param name="pos" select="position()"/>
                                </xsl:call-template>
                            </Reference>
                        </Payment>
                    </xsl:if>
                </xsl:for-each>
            </Trailer>
        </xsl:template>
    </xsl:stylesheet>

> > # #

 <Trailer> 
             <Payment>  
              <Reference>Debit,TMU/2023/1059 A ,TMU/2023/1019 A ,TMU/2023/1020 A, Debit,56011846 A 
    </Reference> 
              </Payment> 
              <Payment> 
               <Reference>Debit,TMU/2023/1059 A ,TMU/2023/1019 A ,TMU/2023/1020 A, Debit,56011846 A 
    </Reference> 
               </Payment>
        </Trailer> 

> #

    <Trailer> 
    <Payment> 
     <Reference>Debit,TMU/2023/1059 A ,TMU/2023/1019 A ,TMU/2023/1020 A </Reference> 
    </Payment> 
    <Payment> 
     <Reference> Debit,56011846 A </Reference>
    </Payment>
    </Trailer>

**> > #This is the xml input which has the nodes SUM and TIME. Most of the sum nodes are empty. I will like to concatenate the all nodes

before the next SUM value to a single reference field.**

<root>
        <row>
             <Time>Debit</Time>
             <Sum>(874,516.25)</Sum>
       </row>
        <row>
               <Time>TMU/2023/1059 A</Time> 
               <Sum></Sum> 
      </row>
       <row> 
              <Time>TMU/2023/1019 A</Time>
               <Sum></Sum>
        </row>
         <row>
           <Time>TMU/2023/1020 A</Time>
           <Sum></Sum>
         </row>
<row>
        <Time>Debit</Time>
      <Sum>(664,297.52)</Sum> 
     </row>
     <row>
            <Time>56011846 A</Time>
             <Sum></Sum>
             </row>
</root>

Solution

  • As I mentioned in the comments, this seems to be a grouping question. If (as you report) your processor supports XSLT 2.0, you should be able to produce the expected output using:

    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">
        <Trailer> 
            <xsl:for-each-group select="row" group-starting-with="row[Sum/text()]">
                <Payment>  
                    <Reference>
                        <xsl:value-of select="current-group()/Time" separator=","/>
                    </Reference> 
                </Payment>
            </xsl:for-each-group>
        </Trailer> 
    </xsl:template>
    
    </xsl:stylesheet>