xslt-2.0soa

how to populate xml elements from a complex type array element in xslt


I have an xml of the following structure.

<DATA_DS>
    <G_2>
        <INFORMATION_TYPE>A</INFORMATION_TYPE>
        <EMPLOYEE_NUMBER>101</EMPLOYEE_NUMBER>
        <FIRST_NAME>X</FIRST_NAME>
        <LAST_NAME>Y</LAST_NAME>
        <RESPONSIBILITY>Responsibility 1</RESPONSIBILITY>
    </G_2>
    <G_2>
        <INFORMATION_TYPE>A</INFORMATION_TYPE>
        <EMPLOYEE_NUMBER>101</EMPLOYEE_NUMBER>
        <FIRST_NAME>X</FIRST_NAME>
        <LAST_NAME>Y</LAST_NAME>
        <RESPONSIBILITY>Responsibility 2</RESPONSIBILITY>
    </G_2>
    <G_2>
        <INFORMATION_TYPE>A</INFORMATION_TYPE>
        <EMPLOYEE_NUMBER>101</EMPLOYEE_NUMBER>
        <FIRST_NAME>X</FIRST_NAME>
        <LAST_NAME>Y</LAST_NAME>
        <RESPONSIBILITY>Responsibility 3</RESPONSIBILITY>
    </G_2>
    <G_2>
        <INFORMATION_TYPE>B</INFORMATION_TYPE>
        <EMPLOYEE_NUMBER>101</EMPLOYEE_NUMBER>
        <FIRST_NAME>X</FIRST_NAME>
        <LAST_NAME>Y</LAST_NAME>
        <RESPONSIBILITY>Responsibility 1</RESPONSIBILITY>
    </G_2>
    <G_2>
        <INFORMATION_TYPE>A</INFORMATION_TYPE>
        <EMPLOYEE_NUMBER>102</EMPLOYEE_NUMBER>
        <FIRST_NAME>M</FIRST_NAME>
        <LAST_NAME>N</LAST_NAME>
        <RESPONSIBILITY>Responsibility 1</RESPONSIBILITY>
    </G_2>
    <G_2>
        <INFORMATION_TYPE>A</INFORMATION_TYPE>
        <EMPLOYEE_NUMBER>102</EMPLOYEE_NUMBER>
        <FIRST_NAME>M</FIRST_NAME>
        <LAST_NAME>N</LAST_NAME>
        <RESPONSIBILITY>Responsibility 2</RESPONSIBILITY>
    </G_2>
    <G_2>
        <INFORMATION_TYPE>A</INFORMATION_TYPE>
        <EMPLOYEE_NUMBER>102</EMPLOYEE_NUMBER>
        <FIRST_NAME>M</FIRST_NAME>
        <LAST_NAME>N</LAST_NAME>
        <RESPONSIBILITY>Responsibility 2</RESPONSIBILITY>
    </G_2>
</DATA_DS>

I have a requirement to create an output xml for each employee in the following format

<EMP>
    <EMPLOYEE_NUMBER>101</EMPLOYEE_NUMBER>
    <FIRST_NAME>X</FIRST_NAME>
    <LAST_NAME>Y</LAST_NAME>
    <RESPONSIBILITY1>Driving</RESPONSIBILITY1>
    <RESPONSIBILITY2>Cooking</RESPONSIBILITY2>
    <RESPONSIBILITY3>Cleaning</RESPONSIBILITY3>
    <RESPONSIBILITY4></RESPONSIBILITY4>
    <RESPONSIBILITY5></RESPONSIBILITY5>
    <RESPONSIBILITY6></RESPONSIBILITY6>
</EMP>
<EMP>
    <EMPLOYEE_NUMBER>102</EMPLOYEE_NUMBER>
    <FIRST_NAME>M</FIRST_NAME>
    <LAST_NAME>N</LAST_NAME>
    <RESPONSIBILITY1>Driving</RESPONSIBILITY1>
    <RESPONSIBILITY2>Singing</RESPONSIBILITY2>
    <RESPONSIBILITY3></RESPONSIBILITY3>
    <RESPONSIBILITY4></RESPONSIBILITY4>
    <RESPONSIBILITY5></RESPONSIBILITY5>
    <RESPONSIBILITY6></RESPONSIBILITY6>
</EMP>

I am using group-by to group the input xml by employee number . For population RESPONSIBILITY1,2 tags I have to check INFORMATION_TYPE for each employee. Only when INFORMATION_TYPE is A INFORMATION_TYPE = 'A' ,I have to populate RESPONSIBILITY1 and succeeding tags in the output for the particular employee. For other INFORMATION_TYPE (ex B) i don't need to take the RESPONSILITY value. (In the example output employee 101 has INFORMATION TYPE A and B , but my requirement is to take RESPONSIBILITY value from only A)

So for employee 101 we have 3 responsibilities Driving, Cooking and Cleaning as INFORMATION TYPE is A.

Similarly for employee 102 we have 2 responsibilities Driving and Singing .

We don't need Values for responsibility when INFORMATION TYPE is not A for an employee.

I have used group-by employee number which groups my input by employee number. I have further grouped the current group by INFORMATION_TYPE . I am unable to populate the RESPONSIBILITY tags in output. How can I achieve the above in XSLT?

XSLT


<EMPLOYEES>
    <xsl:for-each-group select="DATA_DS/G_2" group-by="EMPLOYEE_NUMBER">
        <EMP>
            <EMPLOYEE_NUMBER>
                <xsl:value-of select="EMPLOYEE_NUMBER"/>
            </EMPLOYEE_NUMBER>
            <FIRST_NAME>
                <xsl:value-of select="FIRST_NAME"/>
            </FIRST_NAME>
            <LAST_NAME>
                <xsl:value-of select="LAST_NAME"/>
            </LAST_NAME>
            <xsl:for-each select="current-group() [INFORMATION_TYPE ='A']">
                <RESPONSIBILITY1>
                    <xsl:value-of select="RESPONSIBILITY[1]"/>
                </RESPONSIBILITY1>
                <RESPONSIBILITY2>
                    <xsl:value-of select="RESPONSIBILITY[2]"/>
                </RESPONSIBILITY2>
                <RESPONSIBILITY3>
                    <xsl:value-of select="RESPONSIBILITY[3]"/>
                </RESPONSIBILITY3>
                <RESPONSIBILITY4>
                    <xsl:value-of select="RESPONSIBILITY[4]"/>
                </RESPONSIBILITY4>
                <RESPONSIBILITY5>
                    <xsl:value-of select="RESPONSIBILITY[4]"/>
                </RESPONSIBILITY5>
                <RESPONSIBILITY6>
                    <xsl:value-of select="RESPONSIBILITY[4]"/>
                </RESPONSIBILITY6>
            </xsl:for-each>
        </EMP>
    </xsl:for-each-group>
</EMPLOYEES>


Solution

  • Instead of the <xsl:for-each select="current-group() [INFORMATION_TYPE ='A']">..</xsl:for-each> you simply want e.g.

            <xsl:variable name="responsibilities" select="current-group()[INFORMATION_TYPE ='A']/RESPONSIBILITY"/>
            <xsl:if test="current-group()[INFORMATION_TYPE ='A']">
                <RESPONSIBILITY1>
                    <xsl:value-of select="$responsibilities[1]"/>
                </RESPONSIBILITY1>
                <RESPONSIBILITY2>
                    <xsl:value-of select="$responsibilities[2]"/>
                </RESPONSIBILITY2>
                <RESPONSIBILITY3>
                    <xsl:value-of select="$responsibilities[3]"/>
                </RESPONSIBILITY3>
                <RESPONSIBILITY4>
                    <xsl:value-of select="$responsibilities[4]"/>
                </RESPONSIBILITY4>
                <RESPONSIBILITY5>
                    <xsl:value-of select="$responsibilities[5]"/>
                </RESPONSIBILITY5>
                <RESPONSIBILITY6>
                    <xsl:value-of select="$responsibilities[6]"/>
                </RESPONSIBILITY6>
            </xsl:if>
    

    as far as I can tell.