How can we convert XML elements into a different namespace in xslt - xslt

I have an input xml
<Request xmlns="http://hgkg.ghg.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AppointmentInfo xmlns="">
<AppointmentId/>
<CountryCode>US</CountryCode>
<Division>A</Division>
</AppointmentInfo>
<AppointDate xmlns="">
<Day>Monday</Day>
<Date>April 2</Date>
<AppointDate>
</Request>
I need output like this
<Request xmlns="http://hgkg.ghg.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AppointmentInfo>
<AppointmentId/>
<CountryCode>US</CountryCode>
<Division>A</Division>
</AppointmentInfo>
<AppointDate>
<Day>Monday</Day>
<Date>April 2</Date>
<AppointDate>
</Request>
i just want to remove xmlns="" in that and assume response AppointmentInfo and AppointDate are in hgkg namespace.I want to transform to it..
please help me

Building on JLRishe's earlier answer, you could try this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*/*">
<xsl:element name="{name()}" namespace="{namespace-uri(/*)}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
This would mean, each element that is not the outermost element (match="*/*") is copied to an output element with the same name, but with the namespace of the outermost element (namespace-uri(/*)).
See if that works...

Related

XSL Move one level Element into other while last one is appearing

Given the input XML data:
<Report_Entry>
<Time_Off_Type_Group>
<Time_Off_Type Descriptor="Sickness Full" />
</Time_Off_Type_Group>
<Time_Off_Type_Group>
<Time_Off_Type Descriptor="Sickness Part" />
</Time_Off_Type_Group>
<Time_Off_Entry_ID>2d90199913fa9fae8</Time_Off_Entry_ID>
<Request_or_Correction>Time Off Request</Request_or_Correction>
</Report_Entry>
As a result, I expect the output data via the condition: "for-each Time_Off_Type_Group move Time_Off_Entry_ID and Request_or_Correction into the Time_Off_Type_Group"
Output example:
<Report_Entry>
<Time_Off_Type_Group>
<Time_Off_Type Descriptor="Sickness Full" />
<Time_Off_Entry_ID>2d90199913fa9fae8</Time_Off_Entry_ID>
<Request_or_Correction>Time Off Request</Request_or_Correction>
</Time_Off_Type_Group>
<Time_Off_Type_Group>
<Time_Off_Type Descriptor="Sickness Part" />
<Time_Off_Entry_ID>2d90199913fa9fae8</Time_Off_Entry_ID>
<Request_or_Correction>Time Off Request</Request_or_Correction>
</Time_Off_Type_Group>
</Report_Entry>
Think templates not for-each, so write a template for the Time_Off_Type_Group elements copying the siblings as children and make sure the default idendity copying does not apply to those siblings:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Time_Off_Type_Group">
<xsl:copy>
<xsl:copy-of select="*, ../(* except Time_Off_Type_Group)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Report_Entry/*[not(self::Time_Off_Type_Group)]"/>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bEzkTcn
Or shortly:
<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:template match="/Report_Entry">
<xsl:variable name="common" select="Time_Off_Entry_ID | Request_or_Correction" />
<xsl:copy>
<xsl:for-each select="Time_Off_Type_Group">
<xsl:copy>
<xsl:copy-of select="* | $common"/>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

How to remove the name space from the XML tags

Could you please tell me how could I remove only the name space xmlns="http://ws.apache.org/ns/synapse" from the XML tags?
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:sap-com:document:sap:rfc:functions">
<soapenv:Body>
<urn:BAPI_QM_DEFECT_RECORDING>
<AMOUNT xmlns="http://ws.apache.org/ns/synapse">1</AMOUNT>
<DEFECT_CODE xmlns="http://ws.apache.org/ns/synapse">393</DEFECT_CODE>
<DEFECT_DESC xmlns="http://ws.apache.org/ns/synapse">393</DEFECT_DESC>
<DEFECT_PID xmlns="http://ws.apache.org/ns/synapse">601000</DEFECT_PID>
<INSPID xmlns="http://ws.apache.org/ns/synapse"/>
<ORDER xmlns="http://ws.apache.org/ns/synapse">20262950</ORDER>
<ORIGIN_PID xmlns="http://ws.apache.org/ns/synapse">600000</ORIGIN_PID>
<OVER_CONSUMP xmlns="http://ws.apache.org/ns/synapse">text</OVER_CONSUMP>
</urn:BAPI_QM_DEFECT_RECORDING></soapenv:Body></soapenv:Envelope>
you can use below code by creating element use local-name which will take name without namespaces:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:sap-com:document:sap:rfc:functions">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="urn:BAPI_QM_DEFECT_RECORDING/*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

XSLT copy without segment name

I have the following XML:
<segment>
<personal_information>
<birth_name>xxx</birth_name>
<created_by>yyy</created_by>
<created_on_timestamp>2018-08-06T06:41:07.000Z</created_on_timestamp>
</personal_information>
<segment>
I want to copy the entire personal_information segment with all elements and sub-segments while adding a new field. I tried this with:
<segment>
<personal_information>
<action>DELETE</action>
<xsl:copy>
<xsl:apply-templates select="child::node()"/>
</xsl:copy>
</personal_information>
</segment>
But this results in the following:
<segment>
<personal_information>
<action>DELETE</action>
<personal_information>
<birth_name>xxx</birth_name>
<created_by>yyy</created_by>
<created_on_timestamp>2018-08-06T06:41:07.000Z</created_on_timestamp>
</personal_information>
</personal_information>
</segment>
Would would be the XSLT code to achieve this as a result:
<segment>
<personal_information>
<action>DELETE</action>
<birth_name>xxx</birth_name>
<created_by>yyy</created_by>
<created_on_timestamp>2018-08-06T06:41:07.000Z</created_on_timestamp>
</personal_information>
</segment>
I do not want to copy all fields one by one.
Instead of using <xsl:copy>, use <xsl:copy-of>, which accepts an XPath expression for the nodes to be included in the copy; in this case only the inner childnodes.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="segment">
<segment>
<personal_information>
<action>DELETE</action>
<xsl:copy-of select="personal_information/*" />
</personal_information>
</segment>
</xsl:template>
</xsl:stylesheet>
You need a identity template and one personal_information with adding one action element:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="personal_information">
<xsl:copy>
<action>DELETE</action>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Updated as per new requirement :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="personal_information">
<action>DELETE</action>
<xsl:apply-templates select="node()"/>
</xsl:template>
</xsl:stylesheet>

add namespace prefix to element and subnodes with xslt

I'd like to copy only header element with all subnodes and add to every subnode prefix "v11"(including header element)
Source xml:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns3:createReservationRequest xmlns:ns3="ns3URL" xmlns:ns2="ns2URL">
<header>
<language isoCountryCode="US" isoLanguageCode="en"/>
<channel name="DT">
<subChannel name="WEBWB">
<subChannel name="WEBWB">
<subChannel name="Functester">
<subChannel name="ecom"/>
</subChannel>
</subChannel>
</subChannel>
</channel>
</header>
<ns3:agentInfo>
<ns2:agentDutyCode>PR</ns2:agentDutyCode>
</ns3:agentInfo>
</ns3:createReservationRequest>
</soap:Body>
</soap:Envelope>
Desired result xml:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v1="v1URL"
xmlns:v11="v11URL">
<soapenv:Body>
<v1:createBookerEventRequest>
<v11:header>
<v11:channel name="DT">
<v11:subChannel name="WEBWB">
<v11:subChannel name="WEBWB">
<v11:subChannel name="Functester">
<v11:subChannel name="ecom"/>
</v11:subChannel>
</v11:subChannel>
</v11:subChannel>
</v11:channel>
</v11:header>
</v1:createBookerEventRequest>
</soapenv:Body>
</soapenv:Envelope>
I've tried to implement this using example from here . I've written the following xsl:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v11="v11URL">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates select="//*[local-name()='header']/*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//*[local-name()='header']/*">
<xsl:element name="v11:{name()}" inherit-namespaces="no">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
But it doesn't copy subchannels into result xml. And also adds unwanted "xmlns:v11="http://example.com/schema/common/ATPCommonServiceTypes/v1" attribute to header subnodes. Any help is appreciated
Here is my (edited) suggestion:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v1="v1URL"
xmlns:v11="v11URL"
xmlns:ns3="ns3URL"
exclude-result-prefixes="soap ns3">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:copy-of select="document('')/xsl:stylesheet/namespace::*[local-name() = ('v1', 'v11')]"/>
<xsl:apply-templates select="#* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(namespace-uri())]">
<xsl:element name="v11:{local-name()}">
<xsl:apply-templates select="#* , node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="ns3:createReservationRequest">
<v1:createBookerEventRequest>
<xsl:apply-templates select="#* , node()"/>
</v1:createBookerEventRequest>
</xsl:template>
<xsl:template match="ns3:agentInfo"/>
</xsl:stylesheet>
I added a xmlns declaration to agentDutyCode since it is missing a namespace declaration:
<ns2:agentDutyCode xmlns:ns2="ns2URL">PR</ns2:agentDutyCode>
Using the source with this stylesheet (templates explained in the comments):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v11="v11URL"
xmlns:v1="v1URL"
xmlns:ns3="ns3URL"
exclude-result-prefixes="ns3">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<!-- Copies Envelope and Body preserving their namespace -->
<xsl:template match="soap:Envelope | soap:Body">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- Creates the createReservationRequest element -->
<xsl:template match="ns3:createReservationRequest">
<v1:createBookerEventRequest>
<xsl:apply-templates/>
</v1:createBookerEventRequest>
</xsl:template>
<!-- Ignores language and agentInfo subtrees -->
<xsl:template match="language"/>
<xsl:template match="ns3:agentInfo"/>
<!-- Matches all other elements -->
<xsl:template match="*">
<xsl:element name="v11:{local-name()}" inherit-namespaces="no">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
<!-- Copies attributes -->
<xsl:template match="#*">
<xsl:copy>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
You will have this result:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<v1:createBookerEventRequest xmlns:v11="v11URL" xmlns:v1="v1URL">
<v11:header>
<v11:channel name="DT">
<v11:subChannel name="WEBWB">
<v11:subChannel name="WEBWB">
<v11:subChannel name="Functester">
<v11:subChannel name="ecom"/>
</v11:subChannel>
</v11:subChannel>
</v11:subChannel>
</v11:channel>
</v11:header>
</v1:createBookerEventRequest>
</soap:Body>
</soap:Envelope>
Here is an XSLT Fiddle where you can see the result.

Handling namespace issues while transforming xml

I am able to transform the xml as per my requirement with the below xml as the input.
<message
xmlns="http://www.origoservices.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<m_control>
<control_timestamp>2013-06-06T14:55:37</control_timestamp>
<initiator_id>ASL</initiator_id>
</m_control>
<m_content>
<b_control>
<quote_type>Single Company</quote_type>
<quote_or_print>Quote And Print</quote_or_print>
<generic_quote_ind>Yes</generic_quote_ind>
<tpsdata>
<tps_quote_type>Comparison</tps_quote_type>
</tpsdata>
</b_control>
<application>
<product>
<tpsdata>
<service_type>QuickQuote</service_type>
<quote_type>Standard</quote_type>
</tpsdata>
</product>
</application>
</m_content>
</message>
But the problem is, sometimes the input XML will contain the refference to Namespace as a prefix to each element .As shown in the xml below the namespace prefix 'ns2' for each element.Below is the xml with 'ns2' namespace prefixes. In this case, my xslt fails and unable to perform the transformation. Could anyone please help me to understand how to handle this namespace issues in xslt, so that xml with and without namespace prefixes can be transformed by the same xslt?
<ns2:message xmlns:ns2="http://www.origoservices.com"
xmlns="http://www.w3.org/2000/09/xmldsig#"
>
<ns2:m_control>
<ns2:control_timestamp>2013-06-06T14:55:37</ns2:control_timestamp>
<ns2:initiator_id>ASL</ns2:initiator_id>
</ns2:m_control>
<ns2:m_content>
<ns2:b_control>
<ns2:quote_type>Single Company</ns2:quote_type>
<ns2:quote_or_print>Quote And Print</ns2:quote_or_print>
<ns2:generic_quote_ind>Yes</ns2:generic_quote_ind>
<ns2:quote_response_status>Error</ns2:quote_response_status>
<ns2:tpsdata>
<ns2:tps_quote_type
xmlns="http://www.origoservices.com"
xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>Comparison</ns2:tps_quote_type>
</ns2:tpsdata>
</ns2:b_control>
<ns2:application>
<ns2:product>
<ns2:tpsdata>
<ns2:service_type>QuickQuote</ns2:service_type>
<ns2:quote_type>Standard</ns2:quote_type>
</ns2:tpsdata>
</ns2:product>
</ns2:application>
</ns2:m_content>
</ns2:message>
I am using below xslt.
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:o="http://www.origoservices.com"
xmlns:dp="http://www.datapower.com/extensions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:date="http://exslt.org/dates-and-times"
extension-element-prefixes="dp"
exclude-result-prefixes="fn date">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="o:b_control/o:quote_type[../o:tpsdata/o:tps_quote_type = 'Comparison']">
<xsl:copy>
<xsl:apply-templates select="#*" />
<xsl:text>Comparison</xsl:text>
</xsl:copy>
</xsl:template>
<xsl:template match="o:tpsdata[o:tps_quote_type = 'Comparison']" />
</xsl:stylesheet>
Let me know if more information is needed.
Regards,
Rahul
After all the discussion on this forum, my issue has been resolved. Below is the corrected xslt to handle the namespace issues that I was facing.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:o="http://www.origoservices.com" xmlns:dp="http://www.datapower.com/extensions" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:date="http://exslt.org/dates-and-times" xmlns:g="http://www.w3.org/2000/09/xmldsig#" version="1.0" extension-element-prefixes="dp" exclude-result-prefixes="fn date">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="o:b_control/o:quote_type[../o:tpsdata/g:tps_quote_type = 'Comparison']">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:text>Comparison</xsl:text>
</xsl:copy>
</xsl:template>
<xsl:template match="o:tpsdata[g:tps_quote_type = 'Comparison']"/>
<xsl:template match="o:b_control/o:quote_type[../o:tpsdata/o:tps_quote_type = 'Comparison']">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:text>Comparison</xsl:text>
</xsl:copy>
</xsl:template>
<xsl:template match="o:tpsdata[o:tps_quote_type = 'Comparison']"/>
</xsl:stylesheet>