I'm struggling to resolve an xml transformation that I'm working on. The Input XML has 2 namespaces which makes it challenging and I need to replace the input XML's namespace value to some other value.
Basically, I am trying to:
xmlns:ns2="http://xmlns.example.com/eventNotify/v1"
with xmlns:ns2="http://xmlns.example.com/eventNotify"
My output xml is almost close to what I want to achieve. Except that,
Problems:
xmlns:ns2="http://xmlns.example.com/eventNotify/v1"
is not changing to xmlns:ns2="http://xmlns.example.com/eventNotify"
xmlns="http://xmlns.example.com/cds/customer"
is missing in the namespace declaration of output xmlxmlns="http://xmlns.example.com/eventNotify"
which shouldn't beExample:
<enterpriseProfile domain="customer" majorVersion="0" minorVersion="30">
became
<enterpriseProfile xmlns="http://xmlns.example.com/eventNotify">customer030<accountNumber>613257179</accountNumber>
Input XML
<?xml version="1.0" encoding="UTF-8"?>
<ns2:accountEventNotify xmlns:ns2="http://xmlns.example.com/eventNotify/v1" xmlns="http://xmlns.example.com/cds/customer" schemaVersion="1">
<ns2:header>
<ns2:employee>
<ns2:opco>ABCD</ns2:opco>
<ns2:number>1111111</ns2:number>
</ns2:employee>
<ns2:sourceSystem>SYS1</ns2:sourceSystem>
<ns2:msgCreateTime>2022-06-15T16:58:30.599Z</ns2:msgCreateTime>
<ns2:businessEvent>
<ns2:event>maintenance</ns2:event>
</ns2:businessEvent>
</ns2:header>
<ns2:accountNumber>123456789</ns2:accountNumber>
<ns2:messageType>CREATE</ns2:messageType>
<ns2:create>
<enterpriseProfile domain="customer" majorVersion="0" minorVersion="30">
<accountNumber>123456789</accountNumber>
<profile>
<customerType>AAA</customerType>
<accountType>AAA</accountType>
<accountStatus>
<statusCode>ACTIVE</statusCode>
<statusDate>2022-06-15</statusDate>
</accountStatus>
<creationDate>2022-06-15</creationDate>
<originSource>FF</originSource>
<accountLinkageFlag>false</accountLinkageFlag>
<welcomeKit>
<welcomeKitFlag>false</welcomeKitFlag>
</welcomeKit>
</profile>
</enterpriseProfile>
</ns2:create>
</ns2:accountEventNotify>
XSL
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://xmlns.example.com/eventNotify"
xmlns:c1="http://xmlns.example.com/cds/customer"
xmlns:ns2="http://xmlns.example.com/eventNotify/v1"
xpath-default-namespace="http://xmlns.example.com/cds/customer"
exclude-result-prefixes="c1">
<!-- remove the empty lines with XSLT -->
<xsl:output method="xml" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<!-- replace the schema version value -->
<xsl:template match="/*/@schemaVersion">
<xsl:attribute name="{name()}">21.22.35</xsl:attribute>
</xsl:template>
<xsl:template match="c1:*">
<xsl:element name="{local-name()}">
<xsl:copy-of
select="namespace::*[not(. = 'http://xmlns.example.com/cds/customer')]" />
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
<!-- remove <accountNumber> -->
<xsl:template match="ns2:accountNumber" />
<!-- Change messageType value from CREATE to ADD -->
<!-- Add <action>A</action> -->
<xsl:template
match="ns2:accountEventNotify/ns2:messageType[.='CREATE']">
<ns2:messageType>ADD</ns2:messageType>
<ns2:action>A</ns2:action>
</xsl:template>
<!-- remove node <ns2:create> but keep its children -->
<xsl:template match="ns2:create">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="ns2:*">
<xsl:copy copy-namespaces="no">
<xsl:copy-of
select="namespace::*[not(. = 'http://xmlns.example.com/cds/customer')]" />
<xsl:copy-of select="@*" />
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Output XML
<?xml version="1.0" encoding="utf-8"?>
<ns2:accountEventNotify xmlns:ns2="http://xmlns.example.com/eventNotify/v1" schemaVersion="1">
<ns2:header>
<ns2:employee>
<ns2:opco>ABCD</ns2:opco>
<ns2:number>1111111</ns2:number>
</ns2:employee>
<ns2:sourceSystem>SYS1</ns2:sourceSystem>
<ns2:msgCreateTime>2022-06-15T16:58:30.599Z</ns2:msgCreateTime>
<ns2:businessEvent>
<ns2:event>maintenance</ns2:event>
</ns2:businessEvent>
</ns2:header>
<ns2:messageType xmlns="http://xmlns.example.com/eventNotify">ADD</ns2:messageType>
<ns2:action xmlns="http://xmlns.example.com/eventNotify">A</ns2:action>
<enterpriseProfile xmlns="http://xmlns.example.com/eventNotify">customer030<accountNumber>613257179</accountNumber>
<profile>
<customerType>AAA</customerType>
<accountType>AAA</accountType>
<accountStatus>
<statusCode>ACTIVE</statusCode>
<statusDate>2022-06-15</statusDate>
</accountStatus>
<creationDate>2022-06-15</creationDate>
<originSource>FF</originSource>
<accountLinkageFlag>false</accountLinkageFlag>
<welcomeKit>
<welcomeKitFlag>false</welcomeKitFlag>
</welcomeKit>
</profile>
</enterpriseProfile>
</ns2:accountEventNotify>
Desired output
<?xml version="1.0" encoding="utf-8"?>
<ns2:accountEventNotify xmlns:ns2="http://xmlns.example.com/eventNotify" xmlns="http://xmlns.example.com/cds/customer" schemaVersion="21.22.35">
<ns2:header>
<ns2:employee>
<ns2:opco>ABCD</ns2:opco>
<ns2:number>1111111</ns2:number>
</ns2:employee>
<ns2:sourceSystem>SYS1</ns2:sourceSystem>
<ns2:msgCreateTime>2022-06-15T16:58:30.599Z</ns2:msgCreateTime>
<ns2:businessEvent>
<ns2:event>maintenance</ns2:event>
</ns2:businessEvent>
</ns2:header>
<ns2:messageType>ADD</ns2:messageType>
<ns2:action>A</ns2:action>
<enterpriseProfile domain="customer" majorVersion="0" minorVersion="30">
<profile>
<customerType>AAA</customerType>
<accountType>AAA</accountType>
<accountStatus>
<statusCode>ACTIVE</statusCode>
<statusDate>2022-06-15</statusDate>
</accountStatus>
<creationDate>2022-06-15</creationDate>
<originSource>FF</originSource>
<accountLinkageFlag>false</accountLinkageFlag>
<welcomeKit>
<welcomeKitFlag>false</welcomeKitFlag>
</welcomeKit>
</profile>
</enterpriseProfile>
</ns2:accountEventNotify>
Try this:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="http://xmlns.example.com/eventNotify"
xmlns:old="http://xmlns.example.com/eventNotify/v1"
xmlns="http://xmlns.example.com/cds/customer"
exclude-result-prefixes="old">
<!-- remove the empty lines with XSLT -->
<xsl:output method="xml" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="* | @*">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- replace the schema version value -->
<xsl:template match="/old:accountEventNotify">
<ns2:accountEventNotify>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="schemaVersion">21.22.35</xsl:attribute>
<xsl:apply-templates/>
</ns2:accountEventNotify>
</xsl:template>
<!-- remove <accountNumber> -->
<xsl:template match="old:accountNumber" />
<!-- Change messageType value from CREATE to ADD -->
<!-- Add <action>A</action> -->
<xsl:template
match="old:accountEventNotify/old:messageType[.='CREATE']">
<ns2:messageType>ADD</ns2:messageType>
<ns2:action>A</ns2:action>
</xsl:template>
<!-- remove node <old:create> but keep its children -->
<xsl:template match="old:create">
<xsl:apply-templates />
</xsl:template>
<!-- rename elements from the old to the new namespace -->
<xsl:template match="old:*">
<xsl:element name="ns2:{local-name()}">
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I think part of your problem may be that you were confused as to which namespaces were which. In this XSLT I bound the prefix old
to the namespace bound to ns2
in the source document, and I think this makes it clearer.
I added a template matching the root element, with the effect that the http://xmlns.example.com/cds/customer
namespace declaration appears on the root element in the output, since that seemed to be one of the things you wanted.
Using the input data from your question, my output was:
<?xml version="1.0" encoding="utf-8"?>
<ns2:accountEventNotify xmlns:ns2="http://xmlns.example.com/eventNotify" xmlns="http://xmlns.example.com/cds/customer" schemaVersion="21.22.35">
<ns2:header>
<ns2:employee>
<ns2:opco>ABCD</ns2:opco>
<ns2:number>1111111</ns2:number>
</ns2:employee>
<ns2:sourceSystem>SYS1</ns2:sourceSystem>
<ns2:msgCreateTime>2022-06-15T16:58:30.599Z</ns2:msgCreateTime>
<ns2:businessEvent>
<ns2:event>maintenance</ns2:event>
</ns2:businessEvent>
</ns2:header>
<ns2:messageType>ADD</ns2:messageType>
<ns2:action>A</ns2:action>
<enterpriseProfile domain="customer" majorVersion="0" minorVersion="30">
<accountNumber>123456789</accountNumber>
<profile>
<customerType>AAA</customerType>
<accountType>AAA</accountType>
<accountStatus>
<statusCode>ACTIVE</statusCode>
<statusDate>2022-06-15</statusDate>
</accountStatus>
<creationDate>2022-06-15</creationDate>
<originSource>FF</originSource>
<accountLinkageFlag>false</accountLinkageFlag>
<welcomeKit>
<welcomeKitFlag>false</welcomeKitFlag>
</welcomeKit>
</profile>
</enterpriseProfile>
</ns2:accountEventNotify>