Search code examples
xmlxsltxslt-2.0file-conversion

two different xml structure same output


I would like to ask for help how to create correct xslt conversion if i have two little different structure of input format. I'm using xsl 2.0 for-each-group, but strugling with second structure.

First structure:

<DELIVERY>
<E1EDP07>
    <E1EDP08>
        <EXIDV>SSCC_CODE_C1</EXIDV>
        <PCKAR>CARTON</PCKAR>
    </E1EDP08>
    <E1EDP08>
        <EXIDV>SSCC_CODE_P1</EXIDV>
        <PCKAR>WP</PCKAR>
    </E1EDP08>
    <E1EDP09>
    <MATNR>PRODUCT_A</MATNR>
    </E1EDP09>
</E1EDP07>

<E1EDP07>
    <E1EDP08>
        <EXIDV>SSCC_CODE_C1</EXIDV>
        <PCKAR>CARTON</PCKAR>
    </E1EDP08>
    <E1EDP08>
        <EXIDV>SSCC_CODE_P1</EXIDV>
        <PCKAR>WP</PCKAR>
    </E1EDP08>
    <E1EDP09>
    <MATNR>PRODUCT_B</MATNR>
    </E1EDP09>
</E1EDP07>

<E1EDP07>
    <E1EDP08>
        <EXIDV>SSCC_CODE_C2</EXIDV>
        <PCKAR>CARTON</PCKAR>
    </E1EDP08>
    <E1EDP08>
        <EXIDV>SSCC_CODE_P2</EXIDV>
        <PCKAR>WP</PCKAR>
    </E1EDP08>
    <E1EDP09>
    <MATNR>PRODUCT_C</MATNR>
    </E1EDP09>
</E1EDP07>
</DELIVERY>

second structure is

<DELIVERY>
<E1EDP07>
    <E1EDP08>
        <EXIDV>SSCC_CODE_C1</EXIDV>
        <PCKAR>CARTON</PCKAR>
    </E1EDP08>
    <E1EDP08>
        <EXIDV>SSCC_CODE_P1</EXIDV>
        <PCKAR>WP</PCKAR>
    </E1EDP08>
    <E1EDP08>   
        <EXIDV>SSCC_CODE_C1</EXIDV>
        <PCKAR>CARTON</PCKAR>
    </E1EDP08>
    <E1EDP08>
        <EXIDV>SSCC_CODE_P1</EXIDV>
        <PCKAR>WP</PCKAR>
    </E1EDP08>
    <E1EDP08>   
        <EXIDV>SSCC_CODE_C2</EXIDV>
        <PCKAR>CARTON</PCKAR>
    </E1EDP08>
    <E1EDP08>
        <EXIDV>SSCC_CODE_P2</EXIDV>
        <PCKAR>WP</PCKAR>
    </E1EDP08>

    <E1EDP09>
        <MATNR>PRODUCT_A</MATNR>
    </E1EDP09>
    <E1EDP09>
        <MATNR>PRODUCT_B</MATNR>
    </E1EDP09>
    <E1EDP09>
        <MATNR>PRODUCT_C</MATNR>
    </E1EDP09>
</E1EDP07>
</DELIVERY>
    

expecting output is:

<EXIDV>SSCC_CODE_C1</EXIDV>
    <MATNR>PRODUCT_A</MATNR>
    <MATNR>PRODUCT_B</MATNR>

<EXIDV>SSCC_CODE_C2</EXIDV>
    <MATNR>PRODUCT_C</MATNR>

I'm using xslt 2.0 with for-each-group. Which is working perfectly for first structure. But with second one all MATNR are repeating which is wrong.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <DELIVERY>
            <xsl:for-each-group select="DELIVERY/E1EDP07/E1EDP08[PCKAR='CARTON']" group-by="EXIDV" >

            <EXIDV>
                <xsl:value-of select="EXIDV"/>
            </EXIDV>

            <xsl:for-each select="current-group()">
                <MATNR>
                    <xsl:value-of select="../E1EDP09/MATNR"/>
                </MATNR>
            </xsl:for-each>

        </xsl:for-each-group>
            
    </DELIVERY>
</xsl:template>
</xsl:stylesheet>

expecting result of both structure

<EXIDV>SSCC_CODE_C1</EXIDV>
    <MATNR>PRODUCT_A</MATNR>
    <MATNR>PRODUCT_B</MATNR>

<EXIDV>SSCC_CODE_C2</EXIDV>
    <MATNR>PRODUCT_C</MATNR>

Solution

  • If I understand correctly the required logic for the 2nd structure (a very big if!), it could be implemented as follows:

    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="/DELIVERY">
        <xsl:variable name="temp">
            <xsl:for-each select="E1EDP07/E1EDP08[PCKAR='CARTON']">
                <xsl:variable name="i" select="position()" />
                <xsl:copy>
                    <xsl:copy-of select="EXIDV | ../E1EDP09[$i]/MATNR"/>
                </xsl:copy>
            </xsl:for-each>
        </xsl:variable>
        <DELIVERY>
            <xsl:for-each-group select="$temp/E1EDP08" group-by="EXIDV" >
                <xsl:copy-of select="EXIDV"/>
                <xsl:copy-of select="current-group()/MATNR"/>
            </xsl:for-each-group>
        </DELIVERY>
    </xsl:template>
    
    </xsl:stylesheet>