dynamic XSLT Transformation - xslt

I have an incoming simple xml request below and need to transform to below SOAP message with correct name space.and in the incoming XML request the name space are not coming so while forming the SOAP message we need to take care of the name space also. Is there any XSLT code snippet which will help me to achieve that.
Note - We need to do this XSLT transformation dynamically like the incoming request can be any element like "GetImageRequest" so based on this element need to construct the name space. (probably we can keep all the name space in one xml file and need to construct the SOAP message)
Incoming XML request:
<request>
<payload>
<GetImageRequest>
<participantId>1191152220010</participantId>
<participantCode>131029</participantCode>
<groupCode>027198</groupCode>
<userType>EE</userType>
<clientName>Test</clientName>
<shoeboxID>123444</shoeboxID>
<imageID>45235</imageID>
</GetImageRequest>
</payload>
</request>
==================
Need to Construct below SOAP message with proper namespace.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<get:GetShoeboxItemRequest xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/GetShoeboxItem">
<get:participantId>1060687620010</get:participantId>
<get:participantCode>1060687620010</get:participantCode>
<get:groupCode>027198</get:groupCode>
<get:userType>EE</get:userType>
<get:clientName>Test</get:clientName>
<get:shoeboxID>123444</get:shoeboxID>
</get:GetShoeboxItemRequest>
</soapenv:Body>
</soapenv:Envelope>
Need a quick help on this . XSLT code snippet would be helpful.

This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pRequestedItemName" select="'Shoebox'"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vLcItemName" select=
"translate($pRequestedItemName, $vUpper, $vLower)"/>
<xsl:variable name="vDynNamespace" select=
"concat('urn:webservice/server/mobile/', $vLcItemName, '/types/v1/Get', 'Item')"/>
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<xsl:element name="get:Get{$pRequestedItemName}ItemRequest"
namespace="{$vDynNamespace}">
<xsl:apply-templates select="/*/*/GetImageRequest/node()"/>
</xsl:element>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
<xsl:template match="*">
<xsl:element name="get:{name()}" namespace="{$vDynNamespace}">
<xsl:copy-of select="namespace::*|#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
When applied on the provided source XML document:
<request>
<payload>
<GetImageRequest>
<participantId>1191152220010</participantId>
<participantCode>131029</participantCode>
<groupCode>027198</groupCode>
<userType>EE</userType>
<clientName>Test</clientName>
<shoeboxID>123444</shoeboxID>
<imageID>45235</imageID>
</GetImageRequest>
</payload>
</request>
produces the wanted, correct result:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<get:GetShoeboxItemRequest
xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/GetItem">
<get:participantId>1191152220010</get:participantId>
<get:participantCode>131029</get:participantCode>
<get:groupCode>027198</get:groupCode>
<get:userType>EE</get:userType>
<get:clientName>Test</get:clientName>
<get:shoeboxID>123444</get:shoeboxID>
<get:imageID>45235</get:imageID>
</get:GetShoeboxItemRequest>
</soapenv:Body>
</soapenv:Envelope>
Explanation:
The full power of the <xsl:element> instruction is used.
Use of AVT (Attribute Value Templates)
The only variable part of the dynamic namespace should be provided as a global parameter by the invoker of the transformation.
If you need to construct a completely dynamic namespace (such as passed in a global parameter by the invoker of the transformation), see this answer.
UPDATE:
The OP clarified in a comment that he can have all request-specific namespaces collected in a separate XML document or in a global parameter.
Here is the solution to this clarified problem:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pRequestData">
<r name="GetImageRequest"
ns="urn:webservice/server/mobile/shoebox/types/v1/GetShoeboxItem"/>
<r name="SaveShoeBoxitemRequest"
ns="urn:webservice/server/mobile/shoebox/types/v1/SaveShoeboxItem"/>
<r name="SaveClaimWithReceiptRequest"
ns="urn:webservice/server/mobile/shoebox/types/v1/SaveClaimAndReceipt"/>
<r name="GetThumbNailImageRequest"
ns="urn:webservice/server/mobile/shoebox/types/v1/GetThumbnail"/>
<r name="AttachReceiptwithExistingClaimRequest"
ns="urn:webservice/server/mobile/shoebox/types/v1/AttachClaimAndReceipt"/>
</xsl:param>
<xsl:variable name="vParams" select="document('')/*/xsl:param[#name='pRequestData']"/>
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<xsl:apply-templates select="/*/*/*"/>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
<xsl:template match="*">
<xsl:param name="pKey" select="local-name()"/>
<xsl:element name="get:{local-name()}" namespace="{$vParams/*[#name = $pKey]/#ns}">
<xsl:copy-of select="namespace::*|#*"/>
<xsl:apply-templates>
<xsl:with-param name="pKey" select="$pKey"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document (the provided one with a second, differently named child of payload):
<request>
<payload>
<GetImageRequest>
<participantId>1191152220010</participantId>
<participantCode>131029</participantCode>
<groupCode>027198</groupCode>
<userType>EE</userType>
<clientName>Test</clientName>
<shoeboxID>123444</shoeboxID>
<imageID>45235</imageID>
</GetImageRequest>
<SaveShoeBoxitemRequest>
<participantId>1191152220010</participantId>
<participantCode>131029</participantCode>
<groupCode>027198</groupCode>
<userType>EE</userType>
<clientName>Test</clientName>
<shoeboxID>123444</shoeboxID>
<imageID>45235</imageID>
</SaveShoeBoxitemRequest>
</payload>
</request>
The wanted, correct (unlike "solutions" in other answers) result is produced:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<get:GetImageRequest
xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/GetShoeboxItem">
<get:participantId>1191152220010</get:participantId>
<get:participantCode>131029</get:participantCode>
<get:groupCode>027198</get:groupCode>
<get:userType>EE</get:userType>
<get:clientName>Test</get:clientName>
<get:shoeboxID>123444</get:shoeboxID>
<get:imageID>45235</get:imageID>
</get:GetImageRequest>
<get:SaveShoeBoxitemRequest
xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/SaveShoeboxItem">
<get:participantId>1191152220010</get:participantId>
<get:participantCode>131029</get:participantCode>
<get:groupCode>027198</get:groupCode>
<get:userType>EE</get:userType>
<get:clientName>Test</get:clientName>
<get:shoeboxID>123444</get:shoeboxID>
<get:imageID>45235</get:imageID>
</get:SaveShoeBoxitemRequest>
</soapenv:Body>
</soapenv:Envelope>

So if i know what all namespace for those 5 elements i can put in one
xml file and can retrieve from that XML file. or as you mentioned can
define those name space in global document.
If you have a map of which namespace to use with which "root" element name, you could just as well keep it in the stylesheet itself.
Here's an example (using made-up namespaces, since you did not specify your own):
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://www.example.com/my"
exclude-result-prefixes="my">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:ns-map>
<ns root="GetImageRequest">urn:webservice/a/b/GetShoeboxItem</ns>
<ns root="SaveShoeBoxitemRequest">urn:webservice/c/d/SaveShoeBoxitemRequest</ns>
<ns root="SaveClaimWithReceiptRequest">urn:webservice/e/f/SaveClaimWithReceiptRequest</ns>
<ns root="GetThumbNailImageRequest">urn:webservice/g/h/GetThumbNailImageRequest</ns>
<ns root="AttachReceiptwithExistingClaimRequest">urn:webservice/i/k/AttachReceiptwithExistingClaimRequest</ns>
</my:ns-map>
<xsl:variable name="root" select="name(/request/payload/*)"/>
<xsl:variable name="ns" select="document('')/xsl:stylesheet/my:ns-map/ns[#root=$root]"/>
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<xsl:apply-templates select="request/payload/*" />
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
<xsl:template match="*" >
<xsl:element name="get:{local-name()}" namespace="{$ns}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>

Related

Trouble with inherent namespace XSLT

I have trouble with namespace. I need this output:
<xyt:arguments xmlns:xyt="urn:xytechsystems.com/XytechAPI"
xmlns:NS1="http://schemahost.amcnetworks.com:8080/amcnesb/schemas">
but have trouble with add this namespace xmlns:xyt="urn:xytechsystems.com/XytechAPI" to the argument
I tried used xsl:namesapce, but think trouble in inherit with node
my xslt:
?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"
xmlns:amc="http://schemahost.amcnetworks.com:8080/amcnesb/schemas/adam"
xmlns:my="http://tempuri.org/dummy"
xmlns:i ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:NS1="http://schemahost.amcnetworks.com:8080/amcnesb/schemas" exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="xml" encoding="UTF-8" version="1.0" indent="yes"/>
<xsl:element name="soapenv:Envelope" >
<xsl:namespace name="i" select="'http://www.w3.org/2001/XMLSchema-instance'"/>
<xsl:namespace name="xyt1"
select="'http://schemas.datacontract.org/2004/07/Xytech.MP.API'"/>
<xsl:namespace name="xyt" select="'urn:xytechsystems.com/XytechAPI'"/>
<xsl:element name="soapenv:Header"/>
<xsl:element name="soapenv:Body"/>
<xsl:element name="xyt:Upsert">
<xsl:element name="xyt:credentials">
</xsl:element>
<xsl:element name="xyt:arguments">
<xsl:namespace name="xyt" select="urn:xytechsystems.com/XytechAPI">
<xsl:namespace name="NS1"
select="'http://schemahost.amcnetworks.com:8080/amcnesb/schemas'"/>
my output:
<soapenv:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xyt1="http://schemas.datacontract.org/2004/07/Xytech.MP.API"
xmlns:xyt="urn:xytechsystems.com/XytechAPI"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body/>
<xyt:Upsert>
<xyt:credentials/>
<xyt:arguments xmlns:NS1="http://schemahost.amcnetworks.com:8080/amcnesb/schemas">
<xsl:namespace name="xyt" select="'urn:xytechsystems.com/XytechAPI'"/>
You've tagged your question xslt-1.0, but xsl:namespace is an XSLT 2.0 instruction.
Given that you're creating elements whose names are known statically, it's easiest to do this using literal result elements. Change:
<xsl:element name="soapenv:Envelope" >
<xsl:namespace name="i" select="'http://www.w3.org/2001/XMLSchema-instance'"/>
<xsl:namespace name="xyt1"
select="'http://schemas.datacontract.org/2004/07/Xytech.MP.API'"/>
<xsl:namespace name="xyt" select="'urn:xytechsystems.com/XytechAPI'"/>
<xsl:element name="soapenv:Header"/>
<xsl:element name="soapenv:Body"/>
<xsl:element name="xyt:Upsert">
<xsl:element name="xyt:credentials">
</xsl:element>
to
<soapenv:Envelope
xmlns:i='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xyt1='http://schemas.datacontract.org/2004/07/Xytech.MP.API'
xmlns:xyt='urn:xytechsystems.com/XytechAPI'>
<soapenv:Header/>
<soapenv:Body/>
<xyt:Upsert>
<xyt:credentials/>
Anyone who has to read your code will be eternally grateful to you.
If you want XSLT to output an element like e.g.
<xyt:arguments xmlns:xyt="urn:xytechsystems.com/XytechAPI"
xmlns:NS1="http://schemahost.amcnetworks.com:8080/amcnesb/schemas">
</xyt:arguments>
then the easiest way and the straight-forwards one is to write it as a literal result element i.e.
<xyt:arguments xmlns:xyt="urn:xytechsystems.com/XytechAPI"
xmlns:NS1="http://schemahost.amcnetworks.com:8080/amcnesb/schemas">
</xyt:arguments>
All use of xsl:element is only needed if you want to compute the name and/or namespace (or at least parts of them) during the execution of the XSLT, based on some input data.
I'm agreeing with #mads-hansen's comment:
The namespace URI is already declared with prefix xyt in an ancestor element hence will not be re-declared in the child element for the same prefix. (That's the namespace-fixup mechanism in XSLT.)
You can change the parent prefixes to be xyt1 so that the xyt prefix is new in the xyt:arguments element, even though it is the same namespace URI.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:NS1="http://schemahost.amcnetworks.com:8080/amcnesb/schemas"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xyt1="urn:xytechsystems.com/XytechAPI"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="xml" encoding="UTF-8" version="1.0" indent="yes"/>
<xsl:template name="xsl:initial-template">
<xsl:element name="soapenv:Envelope" >
<xsl:element name="soapenv:Header"/>
<xsl:element name="soapenv:Body"/>
<xsl:element name="xyt1:Upsert">
<xsl:element name="xyt1:credentials" />
<xsl:element name="xyt:arguments" namespace="urn:xytechsystems.com/XytechAPI">
<xsl:namespace name="NS1" select="'http://schemahost.amcnetworks.com:8080/amcnesb/schemas'"/>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
gives
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xyt1="http://schemas.datacontract.org/2004/07/Xytech.MP.API">
<soapenv:Header/>
<soapenv:Body/>
<xyt1:Upsert xmlns:xyt1="urn:xytechsystems.com/XytechAPI">
<xyt1:credentials/>
<xyt:arguments xmlns:NS1="http://schemahost.amcnetworks.com:8080/amcnesb/schemas" xmlns:xyt="urn:xytechsystems.com/XytechAPI"/>
</xyt1:Upsert>
</soapenv:Envelope>
but I don't see why that is preferable to using the same xyt prefix everywhere in the document.

How to Add different name spaces to XML payload using XSLT

I have a simple a XML Payload request, I need to add mutiple namespaces. I have tried a lot but with any luck. Could you help how to transform the XML request,
Payload
<insert>
<u_email_domain>Test.eu</u_email_domain>
<u_cost_center>costcenter123</u_cost_center>
<u_department>ItDepartment</u_department>
<u_family_name>Donald</u_family_name>
<u_first_name>Trump</u_first_name>
<u_foreseen_end_date/>
<u_hris_id>1000091</u_hris_id>
<u_job_title>Manager</u_job_title>
<u_location>newyork</u_location>
<u_manager_hris_id>10000421</u_manager_hris_id>
<u_notification_recipients>dummy#email.com</u_notification_recipients>
<u_vip>NO</u_vip>
</insert>
Expected Result
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://www.service-now.com/u_hr_is">
<soapenv:Body>
<u:insert>
<u:u_email_domain>Test.eu</u:u_email_domain>
<u:u_cost_center>costcenter123</u:u_cost_center>
<u:u_department>ItDepartment</u:u_department>
<u:u_family_name>Donald</u:u_family_name>
<u:u_first_name>Trump</u:u_first_name>
<u:u_hris_id>1000091</u:u_hris_id>
<u:u_job_title>Manager</u:u_job_title>
<u:u_location>newyork</u:u_location>
<u:u_manager_hris_id>10000421</u:u_manager_hris_id>
<u:u_vip>NO</u:u_vip>
</u:insert>
</soapenv:Body>`enter code here`
</soapenv:Envelope>
Try this:
<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:template match="/insert">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://www.service-now.com/u_hr_is">
<soapenv:Body>
<u:insert>
<u:u_email_domain>
<xsl:value-of select="u_email_domain"/>
</u:u_email_domain>
<u:u_cost_center>
<xsl:value-of select="u_cost_center"/>
</u:u_cost_center>
<u:u_department>
<xsl:value-of select="u_department"/>
</u:u_department>
<u:u_family_name>
<xsl:value-of select="u_family_name"/>
</u:u_family_name>
<u:u_first_name>
<xsl:value-of select="u_first_name"/>
</u:u_first_name>
<u:u_hris_id>
<xsl:value-of select="u_hris_id"/>
</u:u_hris_id>
<u:u_job_title>
<xsl:value-of select="u_job_title"/>
</u:u_job_title>
<u:u_location>
<xsl:value-of select="u_location"/>
</u:u_location>
<u:u_manager_hris_id>
<xsl:value-of select="u_manager_hris_id"/>
</u:u_manager_hris_id>
<u:u_vip>
<xsl:value-of select="u_vip"/>
</u:u_vip>
</u:insert>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>

Values are not present in transformed xml in xslt transformation

I am trying to transform one xml using xslt but I am getting empty xml nodes. Please let me know what I am missing.
My source xml is:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:ProcessPartsOrder xmlns="http://www.host.com/ERP/Sales/Entities" xmlns:ns2="http://www.host.com/ERP/Sales/ProcessPartsOrder" xmlns:ns4="http://www.host.com/ERP/Sales/ValueObjects" xmlns:ns3="http://www.host.com/ERP/Sales/Aggregates/PartsOrder">
<ns2:MessageHeader>
<CultureCode>en-US</CultureCode>
<SenderNameCode>S3</SenderNameCode>
<CreationDateTime>2019-03-19T22:48:16</CreationDateTime>
<BODID>e27c5244-4f18-4343-a15f-e509b8a75802</BODID>
</ns2:MessageHeader>
</ns2:ProcessPartsOrder>
I want to transform into below format:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:proc="http://www.host.com/ERP/Sales/ProcessPartsOrder" xmlns:ent="http://www.host.com/ERP/Sales/Entities" xmlns:par="http://www.host.com/ERP/Sales/Aggregates/PartsOrder" xmlns:val="http://www.host.com/ERP/Sales/ValueObjects">
<soapenv:Header/>
<soapenv:Body>
<proc:ProcessPartsOrder>
<proc:MessageHeader>
<ent:CultureCode>en-US</ent:CultureCode>
<ent:SenderNameCode>S3</ent:SenderNameCode>
<ent:CreationDateTime>2013-01-23T12:41:36-05:00</ent:CreationDateTime>
<ent:BODID>e27c5244-4f18-4343-a15f-e509b8a75802</ent:BODID>
</proc:MessageHeader>
</proc:ProcessPartsOrder>
</soapenv:Body>
</soapenv:Envelope>
My xslt looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="http://www.host.com/ERP/Sales/CustomerOrderManagement"
xmlns:ns3="http://www.host.com/ERP/Sales/Aggregates/PartsOrder"
xmlns:ns4="http://www.host.com/ERP/Sales/ValueObjects"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="ns2 ns3 ns4 xs">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/*">
<soapenv:Envelope xmlns="http://www.host.com/ERP/Sales/CustomerOrderManagement"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:proc="http://www.host.com/ERP/Sales/ProcessPartsOrder"
xmlns:ent="http://www.host.com/ERP/Sales/Entities"
xmlns:par="http://www.host.com/ERP/Sales/Aggregates/PartsOrder"
xmlns:val="http://www.host.com/ERP/Sales/ValueObjects">
<soapenv:Header/>
<soapenv:Body>
<proc:ProcessPartsOrder>
<proc:MessageHeader>
<ent:CultureCode>
<xsl:value-of select="/ns2:ProcessPartsOrder/ns2:MessageHeader/CultureCode"/>
</ent:CultureCode>
<ent:SenderNameCode>
<xsl:value-of select="ns2:ProcessPartsOrder/ns2:MessageHeader/SenderNameCode"/>
</ent:SenderNameCode>
<ent:CreationDateTime>
<xsl:value-of select="ns2:ProcessPartsOrder/ns2:MessageHeader/CreationDateTime"/>
</ent:CreationDateTime>
<ent:BODID>
<xsl:value-of select="ns2:ProcessPartsOrder/ns2:MessageHeader/BODID"/>
</ent:BODID>
</proc:MessageHeader>
</proc:ProcessPartsOrder>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>
All I am getting an expected xml with empty values.
I believe I am missing something for which I need help.
Thanks.
You were giving the XPaths to the values a different namespace than in the source. Hence they return empty. The namespace itself differs.
In your source you define the default namespace as
xmlns="http://www.host.com/ERP/Sales/Entities"
But the ns2 namespace in the XSLT is defined as
xmlns:ns2="http://www.host.com/ERP/Sales/CustomerOrderManagement"
Or course you have to use the same namespace in the XPath expression of the XSLT. There you defined the first namespace as proc. So change your template to the following
<xsl:template match="/">
<soapenv:Envelope xmlns="http://www.host.com/ERP/Sales/CustomerOrderManagement"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:proc="http://www.host.com/ERP/Sales/ProcessPartsOrder"
xmlns:ent="http://www.host.com/ERP/Sales/Entities"
xmlns:par="http://www.host.com/ERP/Sales/Aggregates/PartsOrder"
xmlns:val="http://www.host.com/ERP/Sales/ValueObjects">
<soapenv:Header/>
<soapenv:Body>
<proc:ProcessPartsOrder>
<proc:MessageHeader>
<ent:CultureCode>
<xsl:value-of select="/proc:ProcessPartsOrder/proc:MessageHeader/ent:CultureCode"/>
</ent:CultureCode>
<ent:SenderNameCode>
<xsl:value-of select="/proc:ProcessPartsOrder/proc:MessageHeader/ent:SenderNameCode"/>
</ent:SenderNameCode>
<ent:CreationDateTime>
<xsl:value-of select="/proc:ProcessPartsOrder/proc:MessageHeader/ent:CreationDateTime"/>
</ent:CreationDateTime>
<ent:BODID>
<xsl:value-of select="/proc:ProcessPartsOrder/proc:MessageHeader/ent:BODID"/>
</ent:BODID>
</proc:MessageHeader>
</proc:ProcessPartsOrder>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
Or, another approach, you can add the namespace
xmlns:ent="http://www.host.com/ERP/Sales/Entities"
to the stylesheet element and add a modified identity template for the ent: elements which changes the namespace of each copied element:
<xsl:template match="ent:*">
<xsl:element name="ent:{local-name()}" namespace="http://www.host.com/ERP/Sales/Entities">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
Then your main template could be simplified to
<xsl:template match="/">
<soapenv:Envelope xmlns="http://www.host.com/ERP/Sales/CustomerOrderManagement"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:proc="http://www.host.com/ERP/Sales/ProcessPartsOrder"
xmlns:ent="http://www.host.com/ERP/Sales/Entities"
xmlns:par="http://www.host.com/ERP/Sales/Aggregates/PartsOrder"
xmlns:val="http://www.host.com/ERP/Sales/ValueObjects">
<soapenv:Header/>
<soapenv:Body>
<proc:ProcessPartsOrder>
<proc:MessageHeader>
<xsl:apply-templates select="/proc:ProcessPartsOrder/proc:MessageHeader/ent:*"/>
</proc:MessageHeader>
</proc:ProcessPartsOrder>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>
To also copy attributes, add an unmodifed identity template.

get node name from namespace

this is my xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:end="http://endpoint.ggg.com/">
<soapenv:Header/>
<soapenv:Body>
<end:onlineExpressRemit>
<channelCode>NBPS</channelCode>
</end:onlineExpressRemit>
</soapenv:Body>
</soapenv:Envelope>
and this is my xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:end="http://endpoint.ggg.com/" >
<xsl:template match="/">
<xsl:value-of name="ggg2" select="/soapenv:Envelope/soapenv:Body/*[namespace-uri()]"/>
</xsl:template>
</xsl:stylesheet>
my expected output is display only
onlineExpressRemit
i am very new for xslt, i try name(), local-name() alot others method, however no luck, i cant retrieve only node-name, any help will do, thank you!
You can try using local-name(soapenv:Envelope/soapenv:Body/*), for example, the following XSL transformation :
<xsl:stylesheet version="1.0" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:end="http://endpoint.ggg.com/" >
<xsl:output method="text" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:element name="root">
<xsl:value-of select="local-name(soapenv:Envelope/soapenv:Body/*)"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
when applied to your XML sample, yield the following output :
<root>onlineExpressRemit</root>
Note: I added <root> element just because in online XSLT processor I used for testing, there was error when root element is absent. Usually, setting <xsl:output> is enough to be able to output a non-XML result : XSLT: Transforming into non-xml content?

XSLT creating content without namespace

I'm transforming an XML to another XML inside wso2esb (uses saxon). There I have following input example:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<root>
<MyElement>content</MyElement>
</root>
</soapenv:Body>
</soapenv:Envelope>
My Problem is now that the my new content <NEW> should not get any namespace. But I get the following output after my XSLT:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<root>
<NEW xmlns="http://ws.apache.org/ns/synapse">content</NEW>
</root>
</soapenv:Body>
</soapenv:Envelope>
I do not want the xmlns="http://ws.apache.org/ns/synapse" declaration in the new Element . When I test with oXygen it does work, but when I run it inside wso2esb I get the I guess default namespace "http://ws.apache.org/ns/synapse".
So I have tried out 3 different ways of creating the NEW element, and
<xsl:stylesheet xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:avintis="http://www.avintis.com/esb" extension-element-prefixes="avintis" version="2.0" exclude-result-prefixes="#all" xpath-default-namespace="">
<xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/soapenv:Envelope|soapenv:Body">
<xsl:copy>
<xsl:apply-templates select="*|text()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:copy>
<!-- FIRST METHOD - THE METHOD I want to use! this will receive the xmlns="http://ws.apache.org/ns/synapse" -->
<NEW>
<xsl:value-of select="MyElement"/>
</NEW>
<!-- Second methodworks - but I need to add xmlns="" to every element and there are a lot-->
<NEW xmlns="">
<xsl:value-of select="MyElement"/>
</NEW>
<!-- Third method works: But not very readable - I would prefer the first method -->
<xsl:element name="NEW">
<xsl:value-of select="MyElement"/>
</xsl:element>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Is there a way to remove this xmlns attribute when using the first method of element creation?
Thanks
The problem is not that there is an unwanted namespace declaration in the serialized output; the problem is that the NEW element is in the wrong namespace. You need to think about what the (expanded) names of the elements and attributes are, and the namespace declarations will look after themselves.
I strongly suspect that the code you are executing is different from what you have shown us. I think it must have the default namespace declaration xmlns="http://ws.apache.org/ns/synapse" on some ancestor of the <NEW> literal result element, probably on the xsl:stylesheet element itself. If that's not the case, then wso2esb is doing something very strange when it runs the code.
Just found the solution by adding a xmlns="" to the <xsl:stylesheet. Seems like WSO2 gives a default namespace when none is specified.
<xsl:stylesheet xmlns="" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:avintis="http://www.avintis.com/esb" extension-element-prefixes="avintis" version="2.0" exclude-result-prefixes="#all" xpath-default-namespace="">
<xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/soapenv:Envelope|soapenv:Body">
<xsl:copy>
<xsl:apply-templates select="*|text()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:copy>
<!-- FIRST METHOD - THE METHOD I want to use! this will receive the xmlns="http://ws.apache.org/ns/synapse" -->
<NEW>
<xsl:value-of select="MyElement"/>
</NEW>
<!-- Second methodworks - but I need to add xmlns="" to every element and there are a lot-->
<NEW xmlns="">
<xsl:value-of select="MyElement"/>
</NEW>
<!-- Third method works: But not very readable - I would prefer the first method -->
<xsl:element name="NEW">
<xsl:value-of select="MyElement"/>
</xsl:element>
</xsl:copy>
</xsl:template>