Reputation: 143
I have a xml which I want to get in the expected format as shown below. I am trying to use apply templates concept to this. But some how, I am not able to see the expected result.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP:ENV>
<SOAP:HEADER/>
<SOAP:BODY>
<OutputResponse>
<RespStructure ID="1">
<RespStatus>Success</RespStatus>
<RespMessage>
<Country>Australia</Country>
<Capital>Canberra</Capital>
</RespMessage>
<RespMessage>
<Country>England</Country>
<Capital>London</Capital>
</RespMessage>
<RespMessage>
<Country>China</Country>
<Capital>Beijing</Capital>
</RespMessage>
</RespStructure>
</OutputResponse>
</SOAP:BODY>
</SOAP:ENV>
Now in this message, I am having RespMessage and RespStatus both as part of RespStructure. But Respstatus is a single nodeset where RespMessage is a multiple values nodeset(Country, Capital). When I am using apply templates, either only first RespMessage is getting selected (2nd repetition not appearing) or Respstatus not giving it's value. I try to get below output.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP:ENV>
<SOAP:HEADER/>
<SOAP:BODY>
<OutputResponse>
<RespStructure ID="1">
<TransactionStatus>Success</TransactionStatus>
<ListOfCountries>
<SelectedCountry>Australia</SelectedCountry>
<FIrstSelectedCapital>Canberra</FIrstSelectedCapital>
</ListOfCountries>
<ListOfCountries>
<SelectedCountry>England</SelectedCountry>
<FIrstSelectedCapital>London</FIrstSelectedCapital>
</ListOfCountries>
<ListOfCountries>
<SelectedCountry>China</SelectedCountry>
<FIrstSelectedCapital>Beijing</FIrstSelectedCapital>
</ListOfCountries>
</RespStructure>
</OutputResponse>
</SOAP:BODY>
</SOAP:ENV>
I am changing all the names of fields, but I should get all multiple nodes without any missing.
I used below code snippet from forum, but I failed to apply. How can I populate RespStatus using below snippet. When I gave different template, both are not called and only one got printed. I tried to change apply templates to more specific nodeset also.
<xsl:template match="@*|node()">
<xsl:apply-templates select="@*|node()" />
</xsl:template>
<xsl:template match="Body">
<SOAPENV>
<Header/>
<OutputResponse>
<xsl:apply-templates select="@*|node()" />
</OutputResponse>
</SOAPENV>
</xsl:template>
<xsl:template match="RespMessage">
<ListOfCountries>
<SelectedCountry><xsl:value-of select="Country" /></SelectedCountry>
<FIrstSelectedCapital><xsl:value-of select="Capital" /></FIrstSelectedCapital>
</ListOfCountries>
</xsl:template>
Thanks for response. Apologies for any spell mistakes.
Upvotes: 1
Views: 108
Reputation: 70648
Looking at your XSL snippet, it should match, and transform all RespMessage elements, unless there is some other part of the XSLT, which you have not shown, that is affecting things.
One issue you do have, and this might be just how you have editted your question, is that your original XML uses the namespace prefix "SOAP", but you have not declared a namespace for this prefix. I would expect the first line to be something like this
<SOAP:ENV xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
Without this, you will not be able to apply your XSLT on it all.
The use of namespaces also means the second template, matching body, won't match anything
<xsl:template match="Body">
(Actually, it won't match anything because it is case sensitive, and in the original XML it is SOAP:BODY)
Looking at the rest of the XSLT, if you want to copy across existing elements without changing, you should be using the identity template. The first template in your XSLT should look like this
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
With this in place, all you need is to add a template to match, and transform RespStatus.
<xsl:template match="RespStatus">
<xsl:element name="TransactionStatus">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="RespStatus">
<xsl:element name="TransactionStatus">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
<xsl:template match="RespMessage">
<xsl:element name="ListOfCountries">
<SelectedCountry><xsl:value-of select="Country" /></SelectedCountry>
<FIrstSelectedCapital><xsl:value-of select="Capital" /></FIrstSelectedCapital>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2