XSLT Soap Message - xslt

I can't change the name of tags in a SOAP response.
I saw a lot of postings about it, but I did not find an applicable solution.
My original XML is:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
<soap:Header>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:4d6b87d8-fe14-4579-ac34-fe841c184a4b</MessageID>
<RelatesTo RelationshipType="Reply" xmlns="http://www.w3.org/2005/08/addressing">uuid:1f9b0c7e-f36c-4fa3-ac2b-2377b57b6634</RelatesTo>
<Action xmlns="http://www.w3.org/2005/08/addressing">http://xxx</Action>
</soap:Header>
<soap:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<OP1 xmlns="http://xxx/">
<OPR>
<OPO>
<Cod>..</Cod>
<A1>hi my...</A1>
</OPO>
</OPR>
</OP1>
</soap:Body>
</soap:Envelope>
I want to change A1 for ANAME.
My xsl is
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="A1">
<ANAME><xsl:apply-templates /></ANAME>
</xsl:template>
</xsl:stylesheet>
Thanks!

Just add a named namespace declaration for your namespace "http://xxx/" to your stylesheet element like this:
xmlns:aaa="http://xxx/"
Then your can match the A1 elements with aaa:A1 in your template:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:aaa="http://xxx/">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="aaa:A1">
<xsl:element name="ANAME" namespace="http://xxx/">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Partial output:
...
<soap:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<OP1 xmlns="http://xxx/">
<OPR>
<OPO>
<Cod>..</Cod>
<ANAME>hi my...</ANAME>
</OPO>
</OPR>
</OP1>
</soap:Body>

Related

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 add root node if not exists

I have some XML and having a difficult time transforming it.
Example XML:
<?xml version="1.0" encoding="utf-8"?>
<Cars xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Car> ... </Car>
</Cars>
I would like to change it to:
<?xml version="1.0" encoding="utf-8"?>
<Depot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Cars>
<Car> ... </Car>
</Cars>
</Depot>
Sounds simple enough but the problem is some data is already in the expected format, in which case I don't want to apply the transform. How do I achieve this?
EDIT
Some starting XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" mlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Cars">
<Depot>
<Cars>
<xsl:apply-templates select="*"/>
</Cars>
</Depot>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I think you only want to match Cars if it is the root element, so instead of your template matching "Cars", change it to match "/Cars"
<xsl:template match="/Cars">
Try this XSLT (which I have slightly amended to get the first template to call the identity template)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsl:output method="xml" indent="yes" />
<xsl:template match="/Cars">
<Depot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:call-template name="identity" />
</Depot>
</xsl:template>
<xsl:template match="#*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I think that it is just necessary to use a choose in the root template to test if the node Depot exists, if not create it:
<xsl:template match="/">
<xsl:choose>
<xsl:when test="Depot">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<Depot>
<xsl:apply-templates/>
</Depot>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
This also gives same output.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsl:template match="Cars">
<Depot>
<xsl:copy-of select="."/>
</Depot>
</xsl:template>
</xsl:stylesheet>

XSL rename element name but namespace in the wrong place

I have an xml and i want to rename/changes the element name and leave everthing unchanges but i facing the unexpected result.
Incoming XML
<?xml version="1.0" encoding="utf-8"?>
<PublishVENDOR baseLanguage="EN" messageID="507085.1468382418796837538" event="1" xmlns="http://store/companies" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<VENDORSet>
<COMPANIES action="Replace">
<ADDRESS1>32 SUMNER STREET</ADDRESS1>
<ADDRESS2>HARTFORD</ADDRESS2>
<ADDRESS3>CT</ADDRESS3>
<ADDRESS4>03342</ADDRESS4>
</COMPANIES>
</VENDORSet>
</PublishVENDOR>
XSL Map
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://store/companies" version="1.0">
<xsl:template match="/ns:PublishVENDOR">
<xsl:element name="SyncVENDOR">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The result
<?xml version="1.0" encoding="utf-8"?>
<SyncMXVENDOR baseLanguage="EN" messageID="507085.1468382418796837538" event="1">
<VENDORSet xmlns="http://www.ibm.com/maximo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<COMPANIES action="Replace">
<ADDRESS1>32 SUMNER STREET</ADDRESS1>
<ADDRESS2>HARTFORD</ADDRESS2>
<ADDRESS3>CT</ADDRESS3>
<ADDRESS4>03342</ADDRESS4>
</COMPANIES>
</VENDORSet>
</SyncVENDOR>
The result that i want is
<?xml version="1.0" encoding="utf-8"?>
<SyncVENDOR baseLanguage="EN" messageID="507085.1468382418796837538" event="1" xmlns="http://store/companies" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<VENDORSet>
<COMPANIES action="Replace">
<ADDRESS1>32 SUMNER STREET</ADDRESS1>
<ADDRESS2>HARTFORD</ADDRESS2>
<ADDRESS3>CT</ADDRESS3>
<ADDRESS4>03342</ADDRESS4>
</COMPANIES>
</VENDORSet>
</SyncVENDOR>
Please somebody help me... and i'm sorry that my english is not good too
Change
<xsl:template match="/ns:PublishVENDOR">
<xsl:element name="SyncVENDOR">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
to
<xsl:template match="/ns:PublishVENDOR">
<SyncVENDOR xmlns="http://store/companies">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="#*|node()"/>
</SyncVENDOR>
</xsl:template>

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.

How can we convert XML elements into a different namespace in 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...