N00b Pr0grammer
N00b Pr0grammer

Reputation: 4647

How to transform an XML adding a child node using XSLT?

I have the following XML document as an input (InputXML) to a Java program that applies a XSL (TransformationXSL) to convert to output XML (OutputXML).

I want to add an extra node as part of the transformation of the input XML. Is there a better way than what is being shown in the (TranformationXSL), as this just tries to match the element and copy what's required??? Any other efficient way / suggestion is much appreciated.

InputXML

<?xml version="1.0" encoding="UTF-8"?>
<tuple>
    <old>
        <Customers>
            <OrderID>10248</OrderID>
            <CustomerID>VINET</CustomerID>
            <EmployeeID>8</EmployeeID>
            <OrderDate>1996-07-04T00:00:00.0</OrderDate>
            <CustomerID>VINET</CustomerID>
            <CompanyName>Vins et alcools Chevalier</CompanyName>
        </Customers>
    </old>
</tuple>

OutputXML

<?xml version="1.0" encoding="UTF-8"?>
<tuple>
    <old>
        <Customers>
            <Orders>
                <OrderID>10248</OrderID>
                <CustomerID>VINET</CustomerID>
                <EmployeeID>8</EmployeeID>
                <OrderDate>1996-07-04T00:00:00.0</OrderDate>
            </Orders>
            <CustomerID>VINET</CustomerID>
            <CompanyName>Vins et alcools Chevalier</CompanyName>                
        </Customers>
    </old>
</tuple>

This is the TransformationXSL that I was talking about. Can this be modified to efficiently transform the input XML to give the desired output XML???

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

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

    <xsl:template match="Customers">
        <Customers>
            <Orders>
                <OrderID>10248</OrderID>
                <CustomerID>VINET</CustomerID>
                <EmployeeID>8</EmployeeID>
                <OrderDate>1996-07-04T00:00:00.0</OrderDate>
            </Orders>
            <CustomerID>VINET</CustomerID>
            <CompanyName>Vins et alcools Chevalier</CompanyName>
        </Customers>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 1

Views: 1305

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 116992

The output you show can be obtained easily by:

XSLT 1.0

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

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

<xsl:template match="Customers">
    <xsl:copy>
        <Orders>
            <xsl:copy-of select="OrderID | CustomerID[1] | EmployeeID | OrderDate"/>
        </Orders>
        <xsl:copy-of select="CustomerID[1] | CompanyName"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Upvotes: 3

Alexey Yakunin
Alexey Yakunin

Reputation: 1771

If double tag CustomerID in the InputXML is an error, then check my solution below.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml"
                version="1.0"
                encoding="utf-8"
                indent="yes"
                standalone="yes"
                omit-xml-declaration="no"/>

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

    <xsl:template match="OrderID">
        <xsl:element name="Orders">
            <xsl:element name="OrderID">
                <xsl:value-of select="../OrderID/text()"/>
            </xsl:element>
            <xsl:element name="CustomerID">
                <xsl:value-of select="../CustomerID/text()"/>
            </xsl:element>
            <xsl:element name="EmployeeID">
                <xsl:value-of select="../EmployeeID/text()"/>
            </xsl:element>
            <xsl:element name="OrderDate">
                <xsl:value-of select="../OrderDate/text()"/>
            </xsl:element>
        </xsl:element>
    </xsl:template>

    <xsl:template match="EmployeeID"/>
    <xsl:template match="OrderDate"/>
</xsl:stylesheet>

Upvotes: 1

Related Questions