1

I want to insert some elements in middle of xml and remove some elements in the XML.

Please find below the XSLT using to convert the xml.

<xsl:template match="/">            
    <xsl:element name="CLASSES">
        <xsl:copy-of select="INPUT/POST/CLASSES/CLASS" />
            <xsl:variable name="previous_id">
                <xsl:value-of select="INPUT/PRE/CLASSES/STUDENTS/STUDENTADD/ID"></xsl:value-of>
            </xsl:variable>
            <xsl:element name="STUDENTS">               
                <xsl:for-each select="INPUT/POST/CLASSES/STUDENTS/STUDENTADD">
                    <xsl:choose>
                        <xsl:when test="$previous_id = ID">
                            <xsl:element name="change_code">
                                <xsl:value-of select="123" />
                            </xsl:element>
                            <xsl:copy-of select="."/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:copy-of select="."/>
                        </xsl:otherwise>
                        </xsl:choose>                           
                </xsl:for-each> 
                <xsl:for-each select="INPUT/PRE/CLASSES/STUDENTS/STUDENTADD">
                    <xsl:element name="change_code">
                        <xsl:value-of select="124" />
                    </xsl:element>
                    <xsl:copy-of select="."/>
                </xsl:for-each>
            </xsl:element>
    </xsl:element>
</xsl:template>

I'm getting the output as below with inserted element.

<CLASSES>
    <CLASS>
        <CLASSNAME>SIXTH</CLASSNAME>
        <NOOFSTUDENT>60</NOOFSTUDENT>
    </CLASS>
    <STUDENTS>
        <change_code>123</change_code>
        <STUDENTADD>
            <ID>1</ID>
            <ADDRESS>
                <POST_TOWN>123456</POST_TOWN>
                <POST_CODE>56859542</POST_CODE>
            </ADDRESS>
            <STARTDATE>29-12-2015</STARTDATE>
        </STUDENTADD>
        <STUDENTADD>
            <ID>2</ID>
            <ADDRESS>
                <POST_TOWN>W4589652</POST_TOWN>
                <POST_CODE>51896</POST_CODE>
            </ADDRESS>
            <STARTDATE>25-12-2016</STARTDATE>
            <END_DATE>25-12-2016</END_DATE>
        </STUDENTADD>
        <change_code>124</change_code>
        <STUDENTADD>
            <ID>1</ID>
            <ADDRESS>
                <POST_TOWN>12345692</POST_TOWN>
                <POST_CODE>56859542</POST_CODE>
            </ADDRESS>
            <STARTDATE>2015-12-29</STARTDATE>
        </STUDENTADD>
    </STUDENTS>
</CLASSES>

What I would like to have is change_code element should come inside STUdENT_ADD aggregate.

How should i change the xslt?

Input XML is below.

<INPUT>
    <POST>
        <CLASSES>
            <CLASS>
                <CLASSNAME>SIXTH</CLASSNAME>
                <NOOFSTUDENT>60</NOOFSTUDENT>
            </CLASS>
            <STUDENTS>
                <STUDENTADD>
                    <ID>1</ID>
                    <ADDRESS>
                        <POST_TOWN>123456</POST_TOWN>
                        <POST_CODE>56859542</POST_CODE>
                    </ADDRESS>
                    <STARTDATE>29-12-2015</STARTDATE>
                </STUDENTADD>
                <STUDENTADD>
                    <ID>2</ID>
                    <ADDRESS>
                        <POST_TOWN>W4589652</POST_TOWN>
                        <POST_CODE>51896</POST_CODE>
                    </ADDRESS>
                    <STARTDATE>25-12-2016</STARTDATE>
                    <END_DATE>25-12-2016</END_DATE>
                </STUDENTADD>
            </STUDENTS>
        </CLASSES>
    </POST>
    <PRE>
        <CLASSES>
            <STUDENTS>
                <STUDENTADD>
                    <ID>1</ID>
                    <ADDRESS>
                        <POST_TOWN>12345692</POST_TOWN>
                        <POST_CODE>56859542</POST_CODE>
                    </ADDRESS>
                    <STARTDATE>2015-12-29</STARTDATE>
                </STUDENTADD>
            </STUDENTS>
        </CLASSES>
    </PRE>
</INPUT>

1 Answer 1

1

The XSLT can be simplified with the use of templates than using <xsl:for-each>. Since a lot of nodes are retained in the output, you can use the identity template to start with.

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
</xsl:template>

Then all the <STUDENTADD> nodes are to be included under <STUDENTS> which can be done by

<xsl:template match="INPUT">
    <CLASSES>
        <xsl:apply-templates select="POST/CLASSES/CLASS" />
        <STUDENTS>
            <xsl:apply-templates select="POST/CLASSES/STUDENTS/STUDENTADD" />
            <xsl:apply-templates select="PRE/CLASSES/STUDENTS/STUDENTADD" />
        </STUDENTS>
    </CLASSES>
</xsl:template>

Lastly, a new node <CHANGE_CODE> is to be added as a child of <STUDENTADD>. The assumption here is that if the ancestor of <STUDENTADD> happens to be <POST> then the value of <CHANGE_CODE> will be 123 and if it is <PRE> then value would be 124.

<xsl:template match="STUDENTADD">
    <xsl:copy>
        <xsl:choose>
            <xsl:when test="ancestor::POST">
                <CHANGE_CODE>123</CHANGE_CODE>
            </xsl:when>
            <xsl:when test="ancestor::PRE">
                <CHANGE_CODE>124</CHANGE_CODE>
            </xsl:when>
        </xsl:choose>
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>

Below is the complete XSLT and output.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" />
    <xsl:strip-space elements="*" />

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="INPUT">
        <CLASSES>
            <xsl:apply-templates select="POST/CLASSES/CLASS" />
            <STUDENTS>
                <xsl:apply-templates select="POST/CLASSES/STUDENTS/STUDENTADD" />
                <xsl:apply-templates select="PRE/CLASSES/STUDENTS/STUDENTADD" />
            </STUDENTS>
        </CLASSES>
    </xsl:template>

    <xsl:template match="STUDENTADD">
        <xsl:copy>
            <xsl:choose>
                <xsl:when test="ancestor::POST">
                    <CHANGE_CODE>123</CHANGE_CODE>
                </xsl:when>
                <xsl:when test="ancestor::PRE">
                    <CHANGE_CODE>124</CHANGE_CODE>
                </xsl:when>
            </xsl:choose>
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Output

<CLASSES>
    <CLASS>
        <CLASSNAME>SIXTH</CLASSNAME>
        <NOOFSTUDENT>60</NOOFSTUDENT>
    </CLASS>
    <STUDENTS>
        <STUDENTADD>
            <CHANGE_CODE>123</CHANGE_CODE>
            <ID>1</ID>
            <ADDRESS>
                <POST_TOWN>123456</POST_TOWN>
                <POST_CODE>56859542</POST_CODE>
            </ADDRESS>
            <STARTDATE>29-12-2015</STARTDATE>
        </STUDENTADD>
        <STUDENTADD>
            <CHANGE_CODE>123</CHANGE_CODE>
            <ID>2</ID>
            <ADDRESS>
                <POST_TOWN>W4589652</POST_TOWN>
                <POST_CODE>51896</POST_CODE>
            </ADDRESS>
            <STARTDATE>25-12-2016</STARTDATE>
            <END_DATE>25-12-2016</END_DATE>
        </STUDENTADD>
        <STUDENTADD>
            <CHANGE_CODE>124</CHANGE_CODE>
            <ID>1</ID>
            <ADDRESS>
                <POST_TOWN>12345692</POST_TOWN>
                <POST_CODE>56859542</POST_CODE>
            </ADDRESS>
            <STARTDATE>2015-12-29</STARTDATE>
        </STUDENTADD>
    </STUDENTS>
</CLASSES>
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much @Aniket. It worked like a charm. One thing i missed out in question is that i only need to add change code in matching id's. I changed your code with when condition <xsl:when test="ancestor::POST and $previous_cd=ID">. your answer is very helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.