Stripping namespace from a particular element in soap message - xslt

MY requirement is to get expected output from the input message using xslt .
The xslt which i am using has been provided for review..
Input message :
<soapenv:Envelope xmlns:v2="http://service..com/esbd/customer/customerlookup/v2"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v1="http://schema..com/esbd//esbSubHeader/v1">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
soapenv:mustUnderstand="0">
<wsse:UsernameToken>
<wsse:Username></wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
1</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
**<base:TrackingInfo xmlns:base="http://base.canonical.something.com/">
<ApplicationId>BMW</ApplicationId>
<MessageID>112</MessageID>
<CorrelationID>2356260273</CorrelationID>
</base:TrackingInfo>**
</soapenv:Header>
<soapenv:Body>
<web:lookUpCustomer xmlns:web="http://webservices.service.something.com/">
<arg0>
<BirthDttm />
</arg0>
</web:lookUpCustomer>
</soapenv:Body>
</soapenv:Envelope>
expected output :
<soapenv:Envelope xmlns:v1="http://schema.something.com/esbd/esbSubHeader/v1"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v2="http://service.something.com/esbd/customer/customerlookup/v2">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="0"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>something</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
something1</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
**<TrackingInfo>
<ApplicationId >
BMW</ApplicationId>
<MessageID >
112</MessageID>
<CorrelationID >
2356260273</CorrelationID>
</TrackingInfo>**
</soapenv:Header>
<soapenv:Body>
<web:lookUpCustomer xmlns:web="http://webservices.service.something.com/">
<arg0>
<BirthDttm />
</arg0>
</web:lookUpCustomer>
</soapenv:Body>
</soapenv:Envelope>
i am trying to get the output using the below xslt
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:base=""http://base.canonical.something.com/""
xmlns:v2="http://service.something.com/esbd/owg/customer/customerlookup/v2"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v1="http://schema.something.com/esbd/owg/esbSubHeader/v1"
exclude-result-prefixes="base v2 v1">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="base:*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="namespace::*[not(. = namespace-uri(..))]"/>
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
but instead of getting expected output getting below O/P message
<soapenv:Envelope xmlns:v1="http://schema.something.com/esbd/esbSubHeader/v1"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v2="http://service.something.com/esbd/customer/customerlookup/v2">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="0"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>something</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
something1</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
**<TrackingInfo>
<ApplicationId xmlns:base="http://base.canonical.something.com/">
BMW</ApplicationId>
<MessageID xmlns:base="http://base.canonical.something.com/">
112</MessageID>
<CorrelationID xmlns:base="http://base.canonical.something.com/">
2356260273</CorrelationID>
</TrackingInfo>**
</soapenv:Header>
<soapenv:Body>
<web:lookUpCustomer xmlns:web="http://webservices.service.something.com/">
<arg0>
<BirthDttm />
</arg0>
</web:lookUpCustomer>
</soapenv:Body>
</soapenv:Envelope>
Could anybody please help me out where exactly i am going wrong ....

In your XML, the prefix base is bound to URI:
"http://base.canonical.something.com/"
Your stylesheet binds it to:
"http://base.canonical.owg.walgreens.com/"
For this reason, the template:
<xsl:template match="base:*">
matches nothing and the default identity transform template is applied to elements whose name starts with the base prefix.
Once you fix that, you should be getting the expected output. Note that the instruction:
<xsl:copy-of select="namespace::*[not(. = namespace-uri(..))]"/>
is unnecessary.
Note also that:
<ApplicationId xmlns:base="http://base.canonical.something.com/">BMW</ApplicationId>
is exactly the same thing as:
<ApplicationId>BMW</ApplicationId>
If you are bothered about the redundant namespace declaration (which only some processors will copy from the original), add one more template to your stylesheet:
<xsl:template match="*[not(namespace-uri())]">
<xsl:element name="{name()}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
or extend the existing one to:
<xsl:template match="base:* | *[not(namespace-uri())]">
<xsl:element name="{local-name()}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
But all of this is just cosmetics: the resulting XML is semantically the same as the one received without making these changes.

Related

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>

WSO2 EI and XSLT Mediator

I have a SOAP call returning the following:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns:getTenantResponse xmlns:ns="http://services.mgt.tenant.carbon.wso2.org">
<ns:return xsi:type="ax2696:TenantInfoBean" xmlns:ax2696="http://beans.common.stratos.carbon.wso2.org/xsd" xmlns:ax2698="http://exception.common.stratos.carbon.wso2.org/xsd" xmlns:ax2700="http://api.user.carbon.wso2.org/xsd" xmlns:ax2702="http://beans.mgt.tenant.carbon.wso2.org/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ax2696:active>true</ax2696:active>
<ax2696:admin>admin</ax2696:admin>
<ax2696:adminPassword xsi:nil="true"/>
<ax2696:createdDate>2020-03-31T18:05:30.321-03:00</ax2696:createdDate>
<ax2696:email>erico#mail.com</ax2696:email>
<ax2696:firstname>erico</ax2696:firstname>
<ax2696:lastname>mtx</ax2696:lastname>
<ax2696:originatedService xsi:nil="true"/>
<ax2696:successKey xsi:nil="true"/>
<ax2696:tenantDomain>dom20.com</ax2696:tenantDomain>
<ax2696:tenantId>1</ax2696:tenantId>
<ax2696:usagePlan/>
</ns:return>
</ns:getTenantResponse>
</soapenv:Body>
</soapenv:Envelope>
I need to treat the return through a XSLT Mediator in WSO2 Enterprise Integrator 6.6.0.
Some of the attributes return with the content:
xsi:nil="true"
I need the my mediator to replace these tags with empty values for my attributes.
My current Mediator is with following:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[#xsi:nil = 'true']" />
</xsl:stylesheet>
The output is coming like this:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns:getTenantResponse xmlns:ns="http://services.mgt.tenant.carbon.wso2.org">
<ns:return xsi:type="ax2696:TenantInfoBean" xmlns:ax2696="http://beans.common.stratos.carbon.wso2.org/xsd" xmlns:ax2698="http://exception.common.stratos.carbon.wso2.org/xsd" xmlns:ax2700="http://api.user.carbon.wso2.org/xsd" xmlns:ax2702="http://beans.mgt.tenant.carbon.wso2.org/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ax2696:active>true</ax2696:active>
<ax2696:admin>admin</ax2696:admin>
<ax2696:adminPassword xsi:nil="true"/>
<ax2696:createdDate>2020-03-31T18:05:30.321-03:00</ax2696:createdDate>
<ax2696:email>erico#skalena.com</ax2696:email>
<ax2696:firstname>erico</ax2696:firstname>
<ax2696:lastname>teixeira</ax2696:lastname>
<ax2696:originatedService xsi:nil="true"/>
<ax2696:successKey xsi:nil="true"/>
<ax2696:tenantDomain>dom20.com</ax2696:tenantDomain>
<ax2696:tenantId>1</ax2696:tenantId>
<ax2696:usagePlan/>
</ns:return>
</ns:getTenantResponse>
</soapenv:Body>
</soapenv:Envelope>
As example:
<ax2696:successKey xsi:nil="true"/>
I need it to become:
<ax2696:successKey></ax2696:successKey>
I need to do this for most of the attributes not only successKey
Thks
Your template matches any element that has a xsi:nil="true" attribute and removes it. If you want to remove only the attribute itself, make it:
<xsl:template match="#xsi:nil[. = 'true']" />
Updated answer
If you want to remove all #xsi:nil='true'
<xsl:template match="#xsi:nil"/>
If you want to remove #xsl:nil='true' only on certain nodes
<xsl:template match="#xsi:nil[local-name(parent::*) = 'originatedService']"/>
See an example here : https://xsltfiddle.liberty-development.net/pNmC4J4/1
Original answer
Not sure I really understand your question. Is this what you are trying to achieve?
Replace
<!-- TEMPLATE #2 -->
<xsl:template match="*[#xsi:nil = 'true']" />
By
<!-- TEMPLATE #2 -->
<xsl:template match="#xsi:nil[. = 'true']">
<xsl:attribute name="nil" namespace="http://www.w3.org/2001/XMLSchema-instance"/>
</xsl:template>
See it working here : https://xsltfiddle.liberty-development.net/pNmC4J4

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.

dynamic XSLT Transformation

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>

Add a new namespace prefix to the body of a SOAP request, that is not present or referenced in the original XML

I have XML list of values that will be populated by a form. Based on the value of a particular element, in this case Type, I need to dynamically construct a SOAP request. Only certain elements from the Source XML will be used, contingent on the Type. In addition, I need to add a namespace prefix to every element in the SOAP body that is not present or referenced in any way in the Source XML.
Given XML input in the following format:
<User>
<Action>Update</Action>
<Id>123-45-5678</Id>
<Type>Student</Type>
<Validate>true</Validate>
<Grade>11</Grade>
<Classroom/>
<UserName/>
<Password/>
</User>
If I apply the following transform:
<xsl:stylesheet version="1.0" xmlns:ztx="http://tempuri.org/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:variable name="Action" select="/User/Action"/>
<xsl:variable name="Id" select="/User/Id"/>
<xsl:variable name="Type" select="/User/Type"/>
<xsl:variable name="Method" select="concat('ztx:', $Action, $Type)"/>
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<xsl:element name="{$Method}">
<xsl:if test="$Action != 'Create'">
<xsl:copy-of select="/User/Id"/>
</xsl:if>
<xsl:if test="$Action != 'Delete'">
<xsl:choose>
<xsl:when test="$Type = 'Teacher'">
<xsl:copy-of select="/User/Classroom"/>
</xsl:when>
<xsl:when test="$Type = 'Student'">
<xsl:copy-of select="/User/Grade"/>
</xsl:when>
<xsl:when test="$Type = 'Administrator'">
<xsl:copy-of select="/User/UserName"/>
<xsl:copy-of select="/User/Password"/>
</xsl:when>
</xsl:choose>
<xsl:copy-of select="/User/Validate"/>
</xsl:if>
</xsl:element>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>
I get the following output:
<soapenv:Envelope xmlns:ztx="http://tempuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<ztx:UpdateStudent>
<Id>123-45-5678</Id>
<Grade>11</Grade>
<Validate>true</Validate>
</ztx:UpdateStudent>
</soapenv:Body>
</soapenv:Envelope>
My desired output, however, is:
<soapenv:Envelope xmlns:ztx="http://tempuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<ztx:UpdateStudent>
<ztx:Id>123-45-5678</ztx:Id>
<ztx:Grade>11</ztx:Grade>
<ztx:Validate>true</ztx:Validate>
</ztx:UpdateStudent>
</soapenv:Body>
</soapenv:Envelope>
I would like to do this elegantly, if possible, and in a single transform. Looking for a generic way, perhaps with another template, to just process every element in the SOAP body and add the namespace, rather than hard-code them individually.
NOTE: I am restricted to XSLT 1.0
Thank you!
Like you mentioned in your question you can add another template to add the namespace prefix to the elements for your SOAP response.
Here is the template
<xsl:template name="addNamespace" match="User/*">
<xsl:element name="{concat('ztx:',name(.))}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
And then you would just change all of your copy-of to apply-templates then to use the new template.