Dear Experts, I have to use multiple for-loops in XSLT.
Presently with my XSLT I generate output with extra nodes at 'GroupDetail'.
Input Request
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:v1="http://xmldefs. ag.com/Applications/eer/V1" xmlns:wsa="http://www.w3.org/2005/08/addressing">
<SOAP-ENV:Header>
<wsa:messageId>04383-34380-3439939</wsa:messageId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<v1:ProcessDistr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<v1:Group xmlns:ns2="http://xmldefs.ag.com/DD/Commons">
<v1:GroupID>437848</v1:GroupID>
<v1:GroupDetails>
<v1:GroupDetail>
<v1:language>De</v1:language>
<v1:description>Deutsch</v1:description>
</v1:GroupDetail>
<v1:GroupDetail>
<v1:language>En</v1:language>
<v1:description>English</v1:description>
</v1:GroupDetail>
</v1:GroupDetails>
<v1:Status>true</v1:Status>
<v1:Parent>45434554</v1:Parent>
</v1:Group>
<v1:Group xmlns:ns2="http://xmldefs.ag.com/DD/Commons">
<v1:GroupID>437849</v1:GroupID>
<v1:GroupDetails>
<v1:GroupDetail>
<v1:language>Tu</v1:language>
<v1:description>Turkish</v1:description>
</v1:GroupDetail>
<v1:GroupDetail>
<v1:language>Fr</v1:language>
<v1:description>French</v1:description>
</v1:GroupDetail>
</v1:GroupDetails>
<v1:Status>true</v1:Status>
<v1:Parent>45434555</v1:Parent>
</v1:Group>
</v1:ProcessDistr>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Output received with another set of Group details and also 'messageId' is missing.
Output received:
<?xml version="1.0" encoding="UTF-8"?>
<ProcessDistr >
<Group >
<GroupID>437848</GroupID>
<GroupDetails>
<GroupDetail>
<language>De</language>
<description>Deutsch</description>
</GroupDetail>
<GroupDetail>
<language>En</language>
<description>English</description>
</GroupDetail>
<GroupDetail>
<language>Tu</language>
<description>Turkish</description>
</GroupDetail>
<GroupDetail>
<language>Fr</language>
<description>French</description>
</GroupDetail>
</GroupDetails>
<Status>true</Status>
<Parent>45434554</Parent>
</Group>
<Group >
<GroupID>437849</GroupID>
<GroupDetails>
<GroupDetail>
<language>De</language>
<description>Deutsch</description>
</GroupDetail>
<GroupDetail>
<language>En</language>
<description>English</description>
</GroupDetail>
<GroupDetail>
<language>Tu</language>
<description>Turkish</description>
</GroupDetail>
<GroupDetail>
<language>Fr</language>
<description>French</description>
</GroupDetail>
</GroupDetails>
<Status>true</Status>
<Parent>45434555</Parent>
</Group>
<messageId/>
</ProcessDistr>
This is XSLT code which I developed
Used XSLT code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:prof="http://ixult.net/ProfileExchange"
xmlns:sap="http://www.sap.com/sapxsl" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsltc="http://xml.apache.org/xalan/xsltc"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v1="http://xmldefs. ag.com/Applications/eer/V1"
xmlns:vwsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ns2="http://xmldefs.vag.com/DD/Commons"
exclude-result-prefixes="vwsu v1 ns2 xsi wsa" xmlns:wsa="http://www.w3.org/2005/08/addressing">
<!-- Output -->
<xsl:output encoding="UTF-8" indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:element name="ProcessDistr">
<xsl:for-each select="//soap:Body/v1:ProcessDistr/v1:Group">
<xsl:element name="Group">
<xsl:element name="GroupID"><xsl:value-of select="v1:GroupID"/></xsl:element>
<xsl:element name="GroupDetails">
<xsl:for-each select="//v1:GroupDetails/v1:GroupDetail">
<xsl:element name="GroupDetail">
<xsl:element name="language"><xsl:value-of select="v1:language"/></xsl:element>
<xsl:element name="Description">
<xsl:value-of select="v1:Description"/></xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
<xsl:element name="Status"><xsl:value-of select="v1:Status"/></xsl:element>
<xsl:element name="Parent"><xsl:value-of select="v1:Parent"/></xsl:element>
</xsl:element>
</xsl:for-each>
<xsl:element name="messageId"><xsl:value-of select="wsa:messageID"/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Output expected:
<?xml version="1.0" encoding="UTF-8"?>
<ProcessDistr >
<Group >
<GroupID>437848</GroupID>
<GroupDetails>
<GroupDetail>
<language>De</language>
<description>Deutsch</description>
</GroupDetail>
<GroupDetail>
<language>En</language>
<description>English</description>
</GroupDetail>
</GroupDetails>
<Status>true</Status>
<Parent>45434554</Parent>
</Group>
<Group >
<GroupID>437849</GroupID>
<GroupDetails>
<GroupDetail>
<language>Tu</language>
<description>Turkish</description>
</GroupDetail>
<GroupDetail>
<language>Fr</language>
<description>French</description>
</GroupDetail>
</GroupDetails>
<Status>true</Status>
<Parent>45434555</Parent>
</Group>
<messageId>04383-34380-3439939</messageId>
</ProcessDistr>
Please help me on this code
Thank you very much.
With Best Regards, Sateesh N
Dear Satish,
The main problem of the provided code is not on line 20, although fixing this helps get the wanted output.
The main problem is that the code doesn't make use of the powerful XSLT processing model, using which the solution can be expressed without any
<xsl:for-each>
instructions. Also, the code can be shrunk and made more compact, understandable and maintainable.Here is a starter solution (30 lines) that shows how this can be done:
When this transformation is applied on the provided XML document:
the wanted, correct result is produced:
XSLT is a wonderful language and when its full power is used it gives us short and elegant solutions. There are good learning resources waiting to be uncovered.
The main problem with your XSLT is this (line 20):
A path that starts with
//
selects all descendants of the root node, regardless of the current context. You only want to process the descendants of the currentv1:Group
, so you need to change it to:Note also that XML is case-sensitive:
will not return the value of an element named
v1:description
.I would also recommend using literal result elements instead of the
xsl:element
instruction. Usexsl:element
when the name of the element needs to be determined at runtime.