Search code examples
xsltxslt-2.0

XSL to add wrapper element based on value change


I want to create a 'wrapper' / parent element around my E1EDL20 elements when some values change. To be able to more or less group on that new element in SAP PO. When the value in ABLAD changes or when I have a new VKORG I need to create the wrapper element. I can create the element but I want the E1EDL20 to be part of that new group.

https://xsltfiddle.liberty-development.net/nbL5Ydw/5

Input xml:

    <?xml version="1.0" encoding="UTF-8"?>
<SHPMNT05>
   <IDOC BEGIN="1">
      <EDI_DC40 SEGMENT="1">
         <TABNAM>EDI_DC40</TABNAM>
      </EDI_DC40>
      <E1EDT20 SEGMENT="1">
         <TKNUM>0000287214</TKNUM>
         <E1EDL20 SEGMENT="1">
            <VBELN>0081018702</VBELN>
            <ABLAD>1</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0100</VKORG>
         </E1EDL20>
         <E1EDL20 SEGMENT="1">
            <VBELN>0081018703</VBELN>
            <ABLAD>1</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0210</VKORG>
         </E1EDL20>
         <E1EDL20 SEGMENT="1">
            <VBELN>0081018723</VBELN>
            <ABLAD>1</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0210</VKORG>
         </E1EDL20>
         <E1EDL20 SEGMENT="1">
            <VBELN>0081018711</VBELN>
            <ABLAD>2</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0200</VKORG>
         </E1EDL20>
         <E1EDL20 SEGMENT="1">
            <VBELN>0081018712</VBELN>
            <ABLAD>2</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0100</VKORG>
         </E1EDL20>
         <E1EDL20 SEGMENT="1">
            <VBELN>0081018708</VBELN>
            <ABLAD>3</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0200</VKORG>
         </E1EDL20>
         <E1EDL20 SEGMENT="1">
            <VBELN>0081018709</VBELN>
            <ABLAD>3</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0100</VKORG>
         </E1EDL20>
      </E1EDT20>
   </IDOC>
</SHPMNT05>

XSL:

   <?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
   
   <xsl:template match="E1EDT20">
      <xsl:copy>
        
         <xsl:for-each select="//E1EDL20">
            <xsl:variable name="stopno" select="ABLAD"/>
            <xsl:variable name="salesorg" select="VKORG"/>

            <xsl:if test = "not ($stopno = preceding-sibling::E1EDL20/ABLAD) or not ($salesorg = preceding-sibling::E1EDL20/VKORG)">
              Grouping
              <GROUPBY><xsl:value-of select="$stopno" />_<xsl:value-of select="$salesorg" />
              </GROUPBY>           
            </xsl:if>  
            
                  <xsl:copy>
                     <xsl:copy-of select="node()"/>
                  </xsl:copy>

         </xsl:for-each>
      </xsl:copy>
      
   </xsl:template>
</xsl:stylesheet>

Current result:

 <SHPMNT05>
   <IDOC BEGIN="1">
      <EDI_DC40 SEGMENT="1">
         <TABNAM>EDI_DC40</TABNAM>
      </EDI_DC40>
      <E1EDT20>
              Grouping
              <GROUPBY>1_0100</GROUPBY>
         <E1EDL20>
            <VBELN>0081018702</VBELN>
            <ABLAD>1</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0100</VKORG>
         </E1EDL20>
              Grouping
              <GROUPBY>1_0210</GROUPBY>
         <E1EDL20>
            <VBELN>0081018703</VBELN>
            <ABLAD>1</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0210</VKORG>
         </E1EDL20>
         <E1EDL20>
            <VBELN>0081018723</VBELN>
            <ABLAD>1</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0210</VKORG>
         </E1EDL20>
              Grouping
              <GROUPBY>2_0200</GROUPBY>
         <E1EDL20>
            <VBELN>0081018711</VBELN>
            <ABLAD>2</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0200</VKORG>
         </E1EDL20>
         <E1EDL20>
            <VBELN>0081018712</VBELN>
            <ABLAD>2</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0100</VKORG>
         </E1EDL20>
              Grouping
              <GROUPBY>3_0200</GROUPBY>
         <E1EDL20>
            <VBELN>0081018708</VBELN>
            <ABLAD>3</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0200</VKORG>
         </E1EDL20>
         <E1EDL20>
            <VBELN>0081018709</VBELN>
            <ABLAD>3</ABLAD>
            <VSTEL>EWM</VSTEL>
            <VKORG>0100</VKORG>
         </E1EDL20>
      </E1EDT20>
   </IDOC>
</SHPMNT05>

Required result:

<SHPMNT05>
    <IDOC BEGIN="1">
        <EDI_DC40 SEGMENT="1">
            <TABNAM>EDI_DC40</TABNAM>
        </EDI_DC40>
        <E1EDT20>
            <GROUPBY>
                <E1EDL20>
                    <VBELN>0081018702</VBELN>
                    <ABLAD>1</ABLAD>
                    <VSTEL>EWM</VSTEL>
                    <VKORG>0100</VKORG>
                </E1EDL20>
            </GROUPBY>
            <GROUPBY>
                <E1EDL20>
                    <VBELN>0081018703</VBELN>
                    <ABLAD>1</ABLAD>
                    <VSTEL>EWM</VSTEL>
                    <VKORG>0210</VKORG>
                </E1EDL20>
                <E1EDL20>
                    <VBELN>0081018723</VBELN>
                    <ABLAD>1</ABLAD>
                    <VSTEL>EWM</VSTEL>
                    <VKORG>0210</VKORG>
                </E1EDL20>
            </GROUPBY>
            <GROUPBY>
                <E1EDL20>
                    <VBELN>0081018711</VBELN>
                    <ABLAD>2</ABLAD>
                    <VSTEL>EWM</VSTEL>
                    <VKORG>0200</VKORG>
                </E1EDL20>
            </GROUPBY>
            <GROUPBY>
                <E1EDL20>
                    <VBELN>0081018712</VBELN>
                    <ABLAD>2</ABLAD>
                    <VSTEL>EWM</VSTEL>
                    <VKORG>0100</VKORG>
                </E1EDL20>
            </GROUPBY>
            <GROUPBY>
                <E1EDL20>
                    <VBELN>0081018708</VBELN>
                    <ABLAD>3</ABLAD>
                    <VSTEL>EWM</VSTEL>
                    <VKORG>0200</VKORG>
                </E1EDL20>
            </GROUPBY>
            <GROUPBY>
                <E1EDL20>
                    <VBELN>0081018709</VBELN>
                    <ABLAD>3</ABLAD>
                    <VSTEL>EWM</VSTEL>
                    <VKORG>0100</VKORG>
                </E1EDL20>
            </GROUPBY>
        </E1EDT20>
    </IDOC>
</SHPMNT05>

As you can see the grouping on salesorg is not working correctly either because I would expect a new group for 0081018711 and 0081018712 (VKORG 0200 / VKORG 0100).

Kind regards,

Mike


Solution

  • It sounds like a use case for group-adjacent e.g.

       <xsl:template match="E1EDT20">
          <xsl:copy>
             <xsl:for-each-group select="E1EDL20" group-adjacent="ABLAD || '|' || VKORG" >
                <GROUPBY>
                  <xsl:copy-of select="current-group()"/>
                </GROUPBY>
             </xsl:for-each-group>
          </xsl:copy>
       </xsl:template>
    

    (or, if that is an XSLT 2 processor, use group-adjacent="concat(ABLAD, '|', VKORG)", as the || operator is XPath/XSLT 3).