XSLT to extract URL Parameters - xslt

can anyone help me to find a way to extract some parameters from URL and save pass it into soap request
URL
https://hostname/ServiceName?Consumer=ABS&ID=3231
I'd take only Consumer name which is ABS and it's id = 3231 and put it into soap as below
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<Consumer>ABS</Consumer>
<ID>3231<ID>
</soapenv:Body>
</soapenv:Envelope>

In XSLT 2.0 or higher, you can use the xsl:analyze-string instruction to extract all query parameters from a URL string:
<xsl:analyze-string select="$URL" regex="[\?&]([^=]+)=([^&]+)">
<xsl:matching-substring>
<xsl:element name="{regex-group(1)}">
<xsl:value-of select="regex-group(2)" />
</xsl:element>
</xsl:matching-substring>
</xsl:analyze-string>
Demo: http://xsltfiddle.liberty-development.net/a9GPfr

if you want to use string formatting functions along with hard coded element name in result
<xsl:variable name="URL">https://hostname/ServiceName?Consumer=ABS&ID=3231</xsl:variable>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<Consumer>
<xsl:value-of select="substring-before(substring-after($URL,'Consumer='),'&')"/>
</Consumer>
<ID>
<xsl:value-of select="substring-after($URL,'ID=')"/>
</ID>
</soapenv:Body>
</soapenv:Envelope>

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>

XSLT transformation adding namespace from child to parent

I am trying to xslt transformation for multiple response files.
I have one input xml :
`
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ser-root:getAllAreasResponse xmlns:ser-root="http://ws.dm.gov.ae/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<return>
<ns1:Area xmlns:ns1="http://schemas.datacontract.org/2004/07/EP4.Integration.Entities.Common">
<ns1:Identity>451</ns1:Identity>
<ns1:NameAr>الحبيه الخامسة</ns1:NameAr>
<ns1:NameEn>Al Hebiah Fifth</ns1:NameEn>
</ns1:Area>
<ns1:Area xmlns:ns1="http://schemas.datacontract.org/2004/07/EP4.Integration.Entities.Common">
<ns1:Identity>451</ns1:Identity>
<ns1:NameAr>الحبيه الخامسة</ns1:NameAr>
<ns1:NameEn>Al Hebiah Fifth</ns1:NameEn>
</ns1:Area>
</return>
</ser-root>
</soapenv:Body>
</soapenv:Envelope>
`
I want output like below.
`
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getAllAreasResponse xmlns:ns2="http://ws.dm.gov.ae/" xmlns:ns3="http://schemas.datacontract.org/2004/07/EP4.Integration.Entities.Common">
<return>
<ns3:Area >
<ns3:Identity>451</ns3:Identity>
<ns3:NameAr>الحبيه الخامسة</ns3:NameAr>
<ns3:NameEn>Al Hebiah Fifth</ns3:NameEn>
</ns3:Area>
<ns3:Area >
<ns3:Identity>452</ns3:Identity>
<ns3:NameAr>الحبيه الثانية</ns3:NameAr>
<ns3:NameEn>Al Hebiah Second</ns3:NameEn>
</ns3:Area>
`
How to write xslt for that?
To change namespace prefixes without changing namespace URIs you can use code like this in XSLT 2.0:
<xsl:template match="soapenv:*" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:element name="S:{local-name()}" namespace="namespace-uri()">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
Define one such template rule for each namespace.
In 1.0, in place of soapenv:* use *[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/']

Stripping namespace from a particular element in soap message

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.

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.

Wildcard with if statement

I am trying to filter out a username for an incoming connection with .xsl file(DataPower appliance). I have 4 scenarios
user#domain.com - needs to stay the way it is.
user#remove.com - need to remove the domain part.
user#domain.com#remove.com - need to remove only the remove part.
user#remove.com.anything - again need to remove this and everything after.
There are 3 variables here. The 'user' can be anything. The domain can be anything. And the .anything after the remove.com, can be anything. #remove.com will ALWAYS be the same. Luckily that is the constant we can use.
Is there a simple if/then statement we can use to do this. We have tried many variations of If, when, contains, and can't seem to get it working. I can paste the code we are currently using if that will help.
Thanks.
A good solution for your problem can be Regex expressions, try "regexp:match(yourExpressionGoesHere)"
and then you just have to write the specific regex for each case.
We figured it out. Sorry to jump the gun, we've been at this a few days.
Here's the code:
<xsl:template match="#* | node()">
<xsl:variable name="userid" select="substring-after(/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Authenticate']/*[local-name()='username'],'#')"/>
<xsl:choose>
<xsl:when test="contains($userid,'remove')">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:*deleted*">
<soapenv:Header />
<soapenv:Body>
<urn:authenticate>
<userId0>
<xsl:value-of select="substring-before(/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Authenticate']/*[local-name()='username'],'#remove.com')"/>
</userId0>
<credential>
<xsl:value-of select="/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Authenticate']/*[local-name()='password']"/>
</credential>
</urn:authenticate>
</soapenv:Body>
</soapenv:Envelope>
</xsl:when>
<xsl:otherwise>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:*deleted*">
<soapenv:Header />
<soapenv:Body>
<urn:authenticate>
<userId0>
<xsl:value-of select="/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Authenticate']/*[local-name()='username']"/>
</userId0>
<credential>
<xsl:value-of select="/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Authenticate']/*[local-name()='password']"/>
</credential>
</urn:authenticate>
</soapenv:Body>
</soapenv:Envelope>
</xsl:otherwise>
</xsl:choose>
</xsl:template>