Adding namespace to child elements using xslt - xslt

below is the input xml:
<ns:TXLife xmlns:ns="http://ACORD.org/Standards/Life/2">
<TXLifeResponse>
<TransRefGUID/>
<TransExeDate/>
<TransExeTime/>
<TransType tc="228"/>
</ns:TXLife>
and below is my XSLT :
xmlns:ns="http://ACORD.org/Standards/Life/2" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:acor="http://www.foresters.com/esb/ws/wsdl/ACORD-v1.0" xmlns:ns="http://ACORD.org/Standards/Life/2">
<soapenv:Header/>
<soapenv:Body>
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
<xsl:template match="node() [local-name(.) = 'TXLife']">
<xsl:element name="ns:{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
By using this tranformation i am not able to add namespace prefix to all the child element of TXLife.
how to add namespace prefix (ns) to all child elements? so that it should look as below
<ns:TXLifeResponse>
<ns:TransRefGUID/>
<ns:TransExeDate/>
<ns:TransExeTime/>
<ns:TransType tc="228"/>
</ns:TXLife>

If you want only TXLife and descendant to be under http://ACORD.org/Standards/Life/2 namespace, use this stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://ACORD.org/Standards/Life/2"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:template match="/">
<soapenv:Envelope>
<soapenv:Header/>
<soapenv:Body>
<xsl:apply-templates/>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
<xsl:template match="*[ancestor-or-self::ns:TXLife]">
<xsl:element name="ns:{local-name()}">
<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>
Output:
<soapenv:Envelope
xmlns:ns="http://ACORD.org/Standards/Life/2"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header />
<soapenv:Body>
<ns:TXLife>
<ns:TXLifeResponse>
<ns:TransRefGUID></ns:TransRefGUID>
<ns:TransExeDate></ns:TransExeDate>
<ns:TransExeTime></ns:TransExeTime>
<ns:TransType tc="228"></ns:TransType>
</ns:TXLifeResponse>
</ns:TXLife>
</soapenv:Body>
</soapenv:Envelope>

Your XML isn't valid, but I assume you just've missed the closing TXLifeResponse element.
The following transformation will do what you want:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<ns:TXLife xmlns:ns="http://ACORD.org/Standards/Life/2">
<TXLifeResponse>
<TransRefGUID/>
<TransExeDate/>
<TransExeTime/>
<TransType tc="228"/>
</TXLifeResponse>
</ns:TXLife>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ns="http://ACORD.org/Standards/Life/2">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:acor="http://www.foresters.com/esb/ws/wsdl/ACORD-v1.0"
xmlns:ns="http://ACORD.org/Standards/Life/2">
<soapenv:Header/>
<soapenv:Body>
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
<xsl:template match="*">
<xsl:element name="ns:{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Output:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:acor="http://www.foresters.com/esb/ws/wsdl/ACORD-v1.0"
xmlns:ns="http://ACORD.org/Standards/Life/2">
<soapenv:Header/>
<soapenv:Body>
<ns:TXLife>
<ns:TXLifeResponse>
<ns:TransRefGUID/>
<ns:TransExeDate/>
<ns:TransExeTime/>
<ns:TransType tc="228"/>
</ns:TXLifeResponse>
</ns:TXLife>
</soapenv:Body>
</soapenv:Envelope>
The template xsl:template match="node()[local-name(.) = 'TXLife']" is somewhat strange to me. What are you trying to accomplish? Maybe we can help explain why this isn't the appropriate way to do it.

Related

How to add SOAP Headers to soap message- XSLT

I'm getting the SOAP request with empty Headers. I want to add custom headers to the incoming request and copy the soap body as is to the response.How to add xml tags in the Headers ?
Below is the incoming request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<input>
<numb>15171</numb>
</input>
</soapenv:Body>
</soapenv:Envelope>
Expected Output:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<Username xmlns="http://blah.com">username</Username>
<Password xmlns="http://blah.com">password</Password>
</soapenv:Header>
<soapenv:Body>
<input>
<numb>15171</numb>
</input>
</soapenv:Body>
</soapenv:Envelope>
Here is my XSLT which I tried:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://soap/envelope/"
version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="soapenv:Header">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
<soapenv:Header>
<Username xmlns="http://blah.com">username</Username>
<Password xmlns="http://blah.com">password</Password>
</soapenv:Header>
</xsl:copy>
</xsl:template>
<xsl:template match="soapenv:Header"/>
</xsl:stylesheet>
Here's how you could do it.
Note that your 'soapenv' namespace in your XSLT was not matching what is defined in your input XML.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="soapenv:Header">
<xsl:copy>
<Username xmlns="http://blah.com">username</Username>
<Password xmlns="http://blah.com">password</Password>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
See it working here: https://xsltfiddle.liberty-development.net/6q1SDkU

Input-Output transformation remove nodes and update nodes

How to translate the given input xml into the output as shown below.
The input xml should be transformed by removing the wsse:Security header completely and EventUser value must be updated with the Username node value.
I tried below xlst. It is not working
XLST -
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="EventUser">
<xsl:copy>
<xsl:value-of select="Username"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Input -
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security mustUnderstandValue="1"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken id="UsernameToken-274">
<wsse:Username>MyUsername</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">Password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<axis2ns682:Create xmlns:axis2ns682="http://g22.test01.org/test02/RF">
<tns:CreateDetails xmlns:tns="http://g22.test01.org/test02/RF">
<tns:EventUser>Event</tns:EventUser>
<tns:PreApprovedTemplateID>221398</tns:PreApprovedTemplateID>
<tns:Priority>High</tns:Priority>
<tns:PlannedImplementation_Start>2017-09-29</tns:PlannedImplementation_Start>
</tns:CreateDetails>
</axis2ns682:Create>
</soapenv:Body>
</soapenv:Envelope>
Output -
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<axis2ns682:Create xmlns:axis2ns682="http://g22.test01.org/test02/RF">
<tns:CreateDetails xmlns:tns="http://g22.test01.org/test02/RF">
<tns:EventUser>MyUsername</tns:EventUser>
<tns:PreApprovedTemplateID>221398</tns:PreApprovedTemplateID>
<tns:Priority>High</tns:Priority>
<tns:PlannedImplementation_Start>2017-09-29</tns:PlannedImplementation_Start>
</tns:CreateDetails>
</axis2ns682:Create>
</soapenv:Body>
</soapenv:Envelope>
You have three problems with your XSLT
You have not accounted for namespaces in your XSLT. In your XML, the elements are in various namespaces (the EventUser element is in namespace http://g22.test01.org/test02/RF as denoted by the tns: prefix.
You have not coded anything to remove the wsse:Security element
The template matching EventUser is selecting Username, which would only would if Username was a child of EventUser. You actually need to select it from the soap:Header
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tns="http://g22.test01.org/test02/RF"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
version="1.0">
<xsl:template match="wsse:Security" />
<xsl:template match="tns:EventUser">
<xsl:copy>
<xsl:value-of select="//soapenv:Header/wsse:Security/wsse:UsernameToken/wsse:Username"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

adding SOAP header in SOAP envelope using XSLT

i have an incoming SOAP message where there were no SOAP header tag present i need to add SOAP header in that. I am using this XSLT for doing this but SOAP HEADER is not getting added.
XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dp="http://www.datapower.com/extensions"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
extension-element-prefixes="dp"
exclude-result-prefixes="dp" >
<xsl:variable name="uuid" select="dp:variable('var://context/txn/uuid')" />
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="soapenv:Header">
<soapenv:Header>
<UUID><xsl:value-of select="$uuid"/></UUID>
</soapenv:Header>
</xsl:template>
</xsl:stylesheet>
The incomig SOAP mesagge can have header tag or it might not have header tag
Input SOAP Message Without Header tag:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<hmhs-medical-acknowledgement id="4080186649" result="FAIL""/>
</soapenv:Body>
</soapenv:Envelope>
Input SOAP Message With Header tag:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<hmhs-medical-acknowledgement id="4080186649" result="FAIL""/>
</soapenv:Body>
</soapenv:Envelope>
Required Output SOAP Message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<UUID>71A4B2FA029D412787B06E07685ED101</UUID>
</soapenv:Header>
<soapenv:Body>
<hmhs-medical-acknowledgement id="4080186649" result="FAIL""/>
</soapenv:Body>
</soapenv:Envelope>
Can somebody help how to add the SOAP header in that.
AFAICT, you want to do:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dp="http://www.datapower.com/extensions"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
extension-element-prefixes="dp">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="uuid" select="dp:variable('var://context/txn/uuid')" />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/soapenv:Envelope">
<xsl:copy>
<soapenv:Header>
<UUID><xsl:value-of select="$uuid"/></UUID>
</soapenv:Header>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="soapenv:Header"/>
</xsl:stylesheet>

xslt Removing particular namespace from root only

I want to remove namespace (xmlns="http://www.cric.com") in the root element and also the comments.
Input xml looks like this
<?xml version="1.0" encoding="UTF-8"?>
<AM xmlns="http://www.cric.com" name="Asmkl">
<!-- Sets a new value to the existing parameter -->
<set>
<Payload>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET">
<soapenv:Header />
<soapenv:Body>
<web:GetCitiesByCountry>
<!--Optional:-->
<web:CountryName>india</web:CountryName>
</web:GetCitiesByCountry>
</soapenv:Body>
</soapenv:Envelope>
</Payload>
<Verb>POST</Verb>
</Set>
</AM>
I have tried
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="*[namespace-uri() = 'http://www.cric.com']">
<xsl:choose>
<xsl:when test="local-name(.)='root'">
<xsl:element name="root">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:when>
<!-- Copy other elemnts -->
<xsl:otherwise>
<xsl:element name="{name()}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Copy the rest -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This stylesheet removes from root but adding the namespace in soapenv:Envelope tag.
Desired output is
<?xml version="1.0" encoding="UTF-8"?>
<AM name="Asmkl">
<Set>
<Payload>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET">
<soapenv:Header />
<soapenv:Body>
<web:GetCitiesByCountry>
<web:CountryName>india</web:CountryName>
</web:GetCitiesByCountry>
</soapenv:Body>
</soapenv:Envelope>
</Payload>
<Verb>POST</Verb>
</Set>
</AM>
but I am getting
<?xml version="1.0" encoding="UTF-8"?><AM name="Asmkl">
<!-- Sets a new value to the existing parameter -->
<Set>
<Payload>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET" xmlns="http://www.cric.com">
<soapenv:Header/>
<soapenv:Body>
<web:GetCitiesByCountry>
<!--Optional:-->
<web:CountryName>india</web:CountryName>
</web:GetCitiesByCountry>
</soapenv:Body>
</soapenv:Envelope>
</Payload>
<Verb>POST</Verb>
</Set>
</AM>
Kindly suggest. XSLT processor is 1.0
How about:
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="*"/>
<!-- move elements in the default namespace into no namespace -->
<xsl:template match="*[namespace-uri() = 'http://www.cric.com']">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
<!-- "copy" all other elements, without copying the default namespace -->
<xsl:template match="*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Applied to your example (after correcting <set> to <Set>!), the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<AM name="Asmkl">
<Set>
<Payload>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<web:GetCitiesByCountry xmlns:web="http://www.webserviceX.NET">
<web:CountryName/>
</web:GetCitiesByCountry>
</soapenv:Body>
</soapenv:Envelope>
</Payload>
<Verb/>
</Set>
</AM>
Note:
I want to remove namespace (xmlns="http://www.cric.com") in the root
element
I am not sure if you realize that the default namespace declared in the root element:
<AM xmlns="http://www.cric.com" name="Asmkl">
is also inherited by the Set and Payload elements.

Match and Add elements with dynamic namespace using xslt

I have some xml as follows...
<ns1:service1 xmlns:ns1="http://foo.com/service_1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns1:SystemInfo>
<ns1:functionMode>Y</ns1:functionMode>
</ns1:SystemInfo>
</ns1:service>
Now I need to take it and do 2 things
Wrap in a SOAP envelope
insert a trans tag in SystemInfo
the following works for wrapping...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name = "transId" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<xsl:copy-of select="/*"/>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>
Now I need to add the tag, problem is we do not know what the Namespace is (and it could change per request). So I can't hardcode it. However, it will already be in the root tag.
So after I would want...
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<ns1:service1 xmlns:ns1="http://foo.com/service_1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns1:SystemInfo>
<ns1:trans />
<ns1:functionMode>Y</ns1:functionMode>
</ns1:SystemInfo>
</ns1:service>
</soapenv:Body>
</soapenv:Envelope>
But this doesn't seem to accomplish it....
<xsl:template match="*[local-name()='SystemInfo']">
<xsl:copy>
<xsl:element name="type"/>
<xsl:call-template name="copy-children"/>
</xsl:copy>
</xsl:template>
<!-- Copy the children of the current node. -->
<xsl:template name="copy-children">
<xsl:copy-of select="./*"/>
</xsl:template>
What should the above be instead?
Instead if using xsl:copy-of which will just copy the current element without allowing you to make any changes, use xsl:apply-templates
<soapenv:Body>
<xsl:apply-templates select="#*|node()"/>
</soapenv:Body>
Then you can write a template to match your SystemInfo element, and add whatever new elements you need. You could even make use of the namespace-uri function to add it with the same namespace.
<xsl:template match="*[local-name()='SystemInfo']">
<xsl:copy>
<xsl:element name="trans" namespace="{namespace-uri()}" />
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="transId"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<xsl:apply-templates select="#*|node()"/>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
<xsl:template match="*[local-name()='SystemInfo']">
<xsl:copy>
<xsl:element name="trans" namespace="{namespace-uri()}" />
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>