the XPath isn't looking for an exact match of the namespace prefix, but the namespace uri associated with that prefix. Thus your input XML could have as you note <soapenv:Envelope>, <soap:Envelope>, <SOAP-ENV:Envelope>, but the XPath will continue to work assuming of course the XML specifies an XML namespace for these elements that matches the namespace uri in your stylesheet,
Original Message:
Sent: Tue August 16, 2022 09:14 AM
From: kandula nagababu
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Steve Linn,
Now we face a issue with different SOAP Envelop requests like <soapenv:Envelope>, <soap:Envelope>, <SOAP-ENV:Envelope>.
How to write a code for above any case match scenario.
Previously written code is working fine for <soapenv:Envelope> Requests, similarly we tried with "and" operator in template match place and we use the separate multiple templates also but those are not working.
Please Check different Requests in the Attachment.
------------------------------
kandula nagababu
Original Message:
Sent: Tue August 02, 2022 05:36 PM
From: Steve Linn
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Kandula,
In xslt, the identity transformations are essentially recursive template calls that build the output from the top down but then inside out. There is a under to covers apply-templates that is done by the xslt engine to run your transformation starting with the root element. Given your xslt does not have a match="/", the template that matches for the root element is <xsl:template match="@* | *"> which is why you see your message 6 and 7 first as it is processing the soapenv:Envelope element. So let's look at that template:
<xsl:template match="@* | *"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> <xsl:message dp:priority="error"> <xsl:text>6th:</xsl:text> <xsl:copy-of select="."/> </xsl:message> </xsl:copy> <xsl:message dp:priority="error"> <xsl:text>7th:</xsl:text> <xsl:copy-of select="."/> </xsl:message></xsl:template>
The xsl copy will copy the current element which will create the
<soapenv:Envelope
element. It then does an apply templates, passing in ALL of its nodes and attributes.
This same template would match the soapenv:Body which would create the <soap:Body and again, it does an apply template, which this time is matched by a different template, as the <iob:varyOn> element is matching
<xsl:template match="soapenv:Body/*"> <xsl:element name="{concat($globalPrefix, ':', 'Reply')}" namespace="{namespace-uri(.)}"> <xsl:apply-templates select="@* | node()"/> <xsl:message dp:priority="error"> <xsl:text>3rd:</xsl:text> <xsl:copy-of select="."/> </xsl:message> <xsl:element name="{concat($globalPrefix, ':', 'faultCode')}" namespace="{namespace-uri(.)}">ESB0017</xsl:element> <xsl:element name="{concat($globalPrefix, ':', 'faultString')}" namespace="{namespace-uri(.)}">Invalid message format</xsl:element> </xsl:element> <xsl:message dp:priority="error"> <xsl:text>8th:</xsl:text> <xsl:copy-of select="."/> </xsl:message></xsl:template>
that template matches all elements that are children of soapEnv:Body, of course there is only one element here, but this time instead of doing a xsl:copy to create the <iob:varyOn> element, it has an xsl:element to create the iob:Reply element instead. It then does an apply templates to pass all of the children and attributes of iob:varyOn, all of which will match the last template, and when that recursion reaches a point where there are no child attributes or nodes to process, the </xsl:copy closes out that element. When this apply-template finally returns, the two xsl:elements will add the two additional elements to the iob:Reply.
There is no "debugger" that I've used. I generated these examples with eclipse so perhaps there is a debugger there that will allow you to step through the input xml and see which template is matching. It's all about understanding xslt and recursion that is inherent in the apply-template processing. I found this on the net years ago which I found useful at the time. Hope it helps https://lenzconsulting.com/how-xslt-works/
Regards,
Steve
------------------------------
Steve Linn
Senior Consulting I/T Specialist
IBM
Original Message:
Sent: Tue August 02, 2022 10:05 AM
From: kandula nagababu
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Steve Linn,
Please guide me How to debug the xslt code for this i used message elements to print in logs see below code here still i am not understand why 6th, 7th printed first and how <iob:varyOn> replaced with <iob:Reply> in DataPower.
Please don't explain how it is replaced, tell me debug process for XSLT through that i can understand it.
------------------------------
kandula nagababu
Original Message:
Sent: Mon August 01, 2022 05:21 PM
From: Steve Linn
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Kandula,
My apologies, missed that, the match on the generic template wasn't handling attributes. Change it to
<!-- all other elements, simply copy them --> <xsl:template match="@* | *"> <xsl:copy> <xsl:apply-templates select="@* | node()" /> </xsl:copy> </xsl:template>
As for adding attributes in the response for the future, it is simply a matter of adding a template match for the element you wish to add the attribute, and then in addition to the xsl:copy and xsl:apply templates, to do an xsl:attribute to add the desired attribute to the matched element. For example, I added before the final template a match for header_user and added an attribute newAttribute="somevalue" with the following:
<!-- add attribute to iob:header_user element --> <xsl:template match="*[local-name() = 'header_user' and namespace-uri() = $globalNamespace]"> <xsl:copy> <xsl:attribute name="newAttribute">somevalue</xsl:attribute> <xsl:apply-templates select="@* | node()" /> </xsl:copy> </xsl:template>
which produced the following with your input
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:iob="http://www.iob.com"> <soapenv:Header /> <soapenv:Body> <iob:Reply> <iob:Header> <iob:header_channel domain="ext">internal</iob:header_channel> <iob:header_user newAttribute="somevalue">nag</iob:header_user> <iob:header_workstation>pronteff</iob:header_workstation> <iob:ReplyStatus>ERR</iob:ReplyStatus> </iob:Header> <iob:header_transactionDate>07072022</iob:header_transactionDate> <iob:header_transactionTime>13:02</iob:header_transactionTime> <iob:faultCode>ESB0017</iob:faultCode> <iob:faultString>Invalid message format</iob:faultString> </iob:Reply> </soapenv:Body></soapenv:Envelope>
Ultimately, these are all pretty standard xslt identity transformation techniques that you should be able to find examples with your favorite search engine.
Regards,
Steve
------------------------------
Steve Linn
Senior Consulting I/T Specialist
IBM
Original Message:
Sent: Mon August 01, 2022 10:14 AM
From: kandula nagababu
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Steve Linn,
Your code is not working when we passing attributes in the Request, adding attributes in the response is also my requirement for future reference.
------------------------------
kandula nagababu
Original Message:
Sent: Fri July 29, 2022 11:06 AM
From: Steve Linn
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Kandula,
So the new requirement:
1. Replace iob:varyOn with iob:Reply
2. Add as a child to iob:Header the element iob:replyStatus
3. Add as a child to iob:Reply the elements iob:faultCode and iob:faultString as before
4. Continue to be dynamic as far as the namespace uri prefix
Please try the following:
<?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:variable name="globalPrefix" select="substring-before(name(/soapenv:Envelope/soapenv:Body/*[1]), ':')" /> <xsl:variable name="globalNamespace" select="namespace-uri(/soapenv:Envelope/soapenv:Body/*[1])" /> <xsl:template match="soapenv:Body/*"> <xsl:element name="{concat($globalPrefix, ':', 'Reply')}" namespace="{namespace-uri(.)}"> <xsl:apply-templates select="@* | node()" /> <xsl:element name="{concat($globalPrefix, ':', 'faultCode')}" namespace="{namespace-uri(.)}">ESB0017</xsl:element> <xsl:element name="{concat($globalPrefix, ':', 'faultString')}" namespace="{namespace-uri(.)}">Invalid message format</xsl:element> </xsl:element> </xsl:template> <xsl:template match="*[local-name() = 'Header' and namespace-uri() = $globalNamespace]"> <xsl:copy> <xsl:apply-templates select="@* | node()" /> <xsl:element name="{concat($globalPrefix, ':', 'ReplyStatus')}" namespace="{namespace-uri(.)}">ERR</xsl:element> </xsl:copy> </xsl:template> <!-- all other elements, simply copy them --> <xsl:template match="*"> <xsl:copy> <xsl:apply-templates select="@* | node()" /> </xsl:copy> </xsl:template></xsl:stylesheet>
Which produces with your input
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:iob="http://www.iob.com"> <soapenv:Header /> <soapenv:Body> <iob:Reply> <iob:Header> <iob:header_channel>extinternal</iob:header_channel> <iob:header_user>nag</iob:header_user> <iob:header_workstation>pronteff</iob:header_workstation> <iob:ReplyStatus>ERR</iob:ReplyStatus> </iob:Header> <iob:header_transactionDate>07072022</iob:header_transactionDate> <iob:header_transactionTime>13:02</iob:header_transactionTime> <iob:faultCode>ESB0017</iob:faultCode> <iob:faultString>Invalid message format</iob:faultString> </iob:Reply> </soapenv:Body></soapenv:Envelope>
Given you want to inject at iob:Header a new element, you need an additional template to match that element, copy the iob:Header element, apply templates to copy all of its current children, and then add the new element.
Regards,
Steve
------------------------------
Steve Linn
Senior Consulting I/T Specialist
IBM
Original Message:
Sent: Thu July 28, 2022 08:12 AM
From: kandula nagababu
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Steve Linn,
Please ignore the previous requirement,
Please check my new requirement below:
Request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:iob="http://www.iob.com">
<soapenv:Header/>
<soapenv:Body>
<iob:varyOn>
<iob:Header>
<iob:header_channel domain="ext">internal</iob:header_channel>
<iob:header_user>nag</iob:header_user>
<iob:header_workstation>pronteff</iob:header_workstation>
</iob:Header>
<iob:header_transactionDate>07072022</iob:header_transactionDate>
<iob:header_transactionTime>13:02</iob:header_transactionTime>
</iob:varyOn>
</soapenv:Body>
</soapenv:Envelope>
Expected output:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:iob="http://www.iob.com">
<soapenv:Header/>
<soapenv:Body>
<iob:Reply>
<iob:Header>
<iob:header_channel domain="ext">internal</iob:header_channel>
<iob:header_user>nag</iob:header_user>
<iob:header_workstation>pronteff</iob:header_workstation>
<iob:replyStatus>ERR</iob:replyStatus>
</iob:Header>
<iob:header_transactionDate>07072022</iob:header_transactionDate>
<iob:header_transactionTime>13:02</iob:header_transactionTime>
<iob:faultCode>ESB0017</iob:faultCode>
<iob:faultString>Invalid message format</iob:faultString>
</iob:Reply>
</soapenv:Body>
</soapenv:Envelope>
Problem: I able to frame the response as expected format except attribute values are not coming with my code as i attached below.
------------------------------
kandula nagababu
Original Message:
Sent: Mon July 25, 2022 08:39 AM
From: Steve Linn
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Kandula,
I received your private message with additional questions, but that does not allow me to respond directly to you as that email's reply address is a do not reply address of this community forum. Please clarify your question here so I can respond. The request as shown above appears to be a web service request to a iob:varyOn web service. The example I provided added the additional information you wanted added to that web service request. Your subsequent question shows an SOAP message with the root body element <iob:Reply> which I'd assume would be your web service's response to the iob:varyOn request you sent?? Are you wanting to manipulate it as well? Or is the transformation on the request something that the web service didn't like? Since you only provided an expected response and not an actual response for comparison it is difficult to determine what your requirement is. I'd also refer you to documentation on xslt identity transformations which the example I provided implements a variation for your specific requirement. There are plenty of sites you can find in an internet search for "xslt identity transformation".
Best Regards,
Steve
------------------------------
Steve Linn
Senior Consulting I/T Specialist
IBM
Original Message:
Sent: Sun July 17, 2022 06:32 AM
From: kandula nagababu
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Steve Linn,
The code is working fine as per the requirement, Thank you so much.
------------------------------
kandula nagababu
Original Message:
Sent: Thu July 14, 2022 02:29 PM
From: Steve Linn
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Kandula,
You can get the prefix from the name of the parent element (iob:varyOn). Try the following
<?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:template match="soapenv:Body/*"> <xsl:copy> <xsl:apply-templates select="@* | node()" /> <xsl:variable name="prefix" select="substring-before(name(), ':')" /> <xsl:element name="{concat($prefix, ':', 'replyStatus')}" namespace="{namespace-uri(.)}">ERR</xsl:element> <xsl:element name="{concat($prefix, ':', 'faultCode')}" namespace="{namespace-uri(.)}">ESB0017</xsl:element> <xsl:element name="{concat($prefix, ':', 'faultString')}" namespace="{namespace-uri(.)}">Invalid message format</xsl:element> </xsl:copy> </xsl:template> <!-- all other elements, simply copy them --> <xsl:template match="*"> <xsl:copy> <xsl:apply-templates select="@* | node()" /> </xsl:copy> </xsl:template></xsl:stylesheet>
------------------------------
Steve Linn
Senior Consulting I/T Specialist
IBM
Original Message:
Sent: Wed July 13, 2022 11:48 AM
From: kandula nagababu
Subject: How to change element prefix dynamically using XSLT in DATAPOWER
Hi Team,
Our requirement is we receiving SOAP request as input, in the "Error rule" we need to construct Error message with the combination of Input request message along with error message.
Here sample input SOAP is:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:iob="http://www.iob.com">
<soapenv:Header/>
<soapenv:Body>
<iob:varyOn>
<iob:header_channel>internal</iob:header_channel>
<iob:header_user>nag</iob:header_user>
<iob:header_workstation>pronteff</iob:header_workstation>
<iob:header_transactionDate>07072022</iob:header_transactionDate>
<iob:header_transactionTime>13:02</iob:header_transactionTime>
</iob:varyOn>
</soapenv:Body>
</soapenv:Envelope>
required output:
<soap:Envelope xmlns:iob="http://www.iob.com" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<iob:varyOn>
<iob:header_channel>internal</iob:header_channel>
<iob:header_user>nag</iob:header_user>
<iob:header_workstation>pronteff</iob:header_workstation>
<iob:header_transactionDate>07072022</iob:header_transactionDate>
<iob:header_transactionTime>13:02</iob:header_transactionTime>
<iob:replyStatus>ERR</iob:replyStatus>
<iob:faultCode>ESB0017</iob:faultCode>
<iob:faultString>Invalid message format</iob:faultString>
</iob:varyOn>
</soap:Body>
</soap:Envelope>
Here Request element prefix was "iob" some times "ns1", "mob" are comming we need to add those name spaces replayStatus,faultCode, and faultString elements prefix also as shown above dynamically.
I tried so many codes those are having static value, how can we pass name prefix dynamically for Response message.
Thanks in Advance.
------------------------------
kandula nagababu
------------------------------