KM6895
KM6895

Reputation: 89

Need help - ADD/Replace/Remove nodes in XML based on conditions using XSLT

I have to transform following two XMLs(Input XML # 1 and Input XML # 2) using XSLT. I would need your help to transform them using XSLT as I'm sturggling to find a solution.

Thanks in advance for your help.

Input XML # 1

<Employee>
<Summary>
    <Employee_ID>12345</Employee_ID>
    <Name>Mel Gibson</Name>
</Summary>
<Personal>
    <First_Name>Mel</First_Name>
    <Last_Name>Gibson</Last_Name>
</Personal>
<Status>
    <Active>Yes</Active>
    <Base_Location>Boston</Base_Location>
</Status>
<Summary_Information>
    <Location>California</Location>
    <Last_Formatted_Name>Samuel Gibson</Last_Formatted_Name>
</Summary_Information>
</Employee>

Condition to transform above XML is

If Last_Name node exists in the XML#1, that node should hold the value of Last_Formatted_Name after transformation and remove Last_Formatted_Name node from XML#1.

Output should look like as below. Please note Last_Name is holding the value of Last_Formatted_Name and Last_Formatted_Name is removed.

<Employee>
<Summary>
    <Employee_ID>12345</Employee_ID>
    <Name>Mel Gibson</Name>
</Summary>
<Personal>
    <First_Name>Mel</First_Name>
    <Last_Name>Samuel Gibson</Last_Name>
</Personal>
<Status>
    <Active>Yes</Active>
    <Base_Location>Boston</Base_Location>
</Status>
<Summary_Information>
    <Location>California</Location>
</Summary_Information>
</Employee>

Input XML # 2

<Employee>
<Summary>
    <Employee_ID>12345</Employee_ID>
    <Name>Mel Gibson</Name>
</Summary>
<Personal>
    <First_Name>Mel</First_Name>
</Personal>
<Status>
    <Active>Yes</Active>
    <Base_Location>Boston</Base_Location>
</Status>
<Summary_Information>
    <Location>California</Location>
    <Last_Formatted_Name>Samuel Gibson</Last_Formatted_Name>
</Summary_Information>
</Employee>

Condition to transform XML# 2 is: If Last_Name does'nt exist in input XML, a node Last_Name should be created right after First_Name node and should hold the value of Last_Formatted_Name

Output should look like below. Please note Last_Name node is created right after First_Name and Last_Formatted_Name node is removed.

<Employee>
<Summary>
    <Employee_ID>12345</Employee_ID>
    <Name>Mel Gibson</Name>
</Summary>
<Personal>
    <First_Name>Mel</First_Name>
    <Last_Name>Samuel Gibson</Last_Name>
</Personal>
<Status>
    <Active>Yes</Active>
    <Base_Location>Boston</Base_Location>
</Status>
<Summary_Information>
    <Location>California</Location>
</Summary_Information>
</Employee>

Following XSLT is what i have written to achieve this, but doesn't produce the output that i wanted.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()" mode="#default">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Personal">

    <xsl:if test="exists(Last_Name)">
    <xsl:copy>
            <xsl:apply-templates/>
        <Last_Name>
            <xsl:value-of select="//Last_Formatted_Name"/>
        </Last_Name>
        </xsl:copy>
    </xsl:if>
</xsl:template>

<xsl:template match="Personal">
<xsl:if test="not(Last_Name)">
    <xsl:copy>
            <xsl:apply-templates/>
        <Last_Name>
            <xsl:value-of select="//Last_Formatted_Name"/>
        </Last_Name>
        </xsl:copy>
    </xsl:if>
</xsl:template>

Upvotes: 2

Views: 527

Answers (1)

Aniket V
Aniket V

Reputation: 3247

Please try the following XSLT

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

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

    <!-- modifies the value of <Last_Name> if it exists -->
    <xsl:template match="Last_Name">
        <xsl:copy>
            <xsl:value-of select="../../Summary_Information/Last_Formatted_Name" />
        </xsl:copy>
    </xsl:template>

    <!-- if <Last_Name> does not exist, creates a last name with the appropriate value -->
    <xsl:template match="Personal[not(Last_Name)]">
        <xsl:copy>
            <xsl:apply-templates />
            <Last_Name>
                <xsl:value-of select="../Summary_Information/Last_Formatted_Name" />
            </Last_Name>
        </xsl:copy>
    </xsl:template>

    <!-- removes the node -->
    <xsl:template match="Last_Formatted_Name" />
</xsl:stylesheet>

Upvotes: 2

Related Questions