Sateesh
Sateesh

Reputation: 53

XSLT transformation with multiple nodes

I have multiple occurence nodes which need to be generated at output using XSLT transformation. Could you please help me on this.

Following XSLT code only generate one node occurrence only. Could you please help me with below XSLT code how to generate multiple nodes elements in Input XML

Input XML

    <?xml version="1.0" encoding="UTF-8" ?> 
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" >
    <soapenv:Body>
    <ns1:getGenResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
    <ns1:getGenReturn xsi:type="soapenc:Array" soapenc:arrayType="xsd:anyType[2]" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
    </ns1:getGenReturn>
    </ns1:getGenResponse>
    <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Gen" xmlns:soapenc=http://schemas.xmlsoap.org/soap/encoding/>
        <name xsi:type="xsd:string">ULM</name> 
         <mail xsi:type="xsd:string">[email protected]</mail> 
    </multiRef>
    <multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:Gen" " xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
         <name xsi:type="xsd:string">ABC</name> 
         <mail xsi:type="xsd:string">[email protected]</mail> 
    </multiRef>
    </soapenv:Body>
    </soapenv:Envelope>

XSLT Code used for this transformation

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" x
 xmlns:response="http://tempuri.org/" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Output -->
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:if test="//soap:Body/multiRef">
<xsl:element name="getGenResponse">
  <xsl:element name="getGenReturn">
                               <xsl:element name="name"><xsl:value-of select="//name"/></xsl:element>

                               <xsl:element name="mail"><xsl:value-of select="//mail"/></xsl:element>
  </xsl:element>
</xsl:element>
</xsl:if>
</xsl:template>

   <!-- 'Copy ' node -->
<xsl:template match="@* | node()">
   <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
   </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Output from above XSLT

<?xml version="1.0" encoding="UTF-8"?>
<getGenResponse>
   <getGenReturn>
      <name> ULM </name>
      <mail>[email protected]<mail>
   </getGenReturn>
/getGenResponse>

Output expected

<?xml version="1.0" encoding="UTF-8"?>
<getGenResponse>
   <getGenReturn>
      <name> ULM </name>
      <mail>[email protected]<mail>
   </getGenReturn>
  <getGenReturn>
      <name>ABC</name>
      <mail>[email protected]<mail>
  </getGenReturn>
/getGenResponse>

Upvotes: 0

Views: 722

Answers (2)

Tim C
Tim C

Reputation: 70598

At you moment all you are doing is testing a multiRef element exists, and outputting only one new getGenReturn element.

All you really need to do is replace the xsl:if with xsl:for-each to select all the elements, then you will get one getGenReturn for each. And also change the xsl:value-of to use a relative path

<xsl:template match="/">
  <xsl:element name="getGenResponse">
    <xsl:for-each select="//soap:Body/multiRef">
      <xsl:element name="getGenReturn">
        <xsl:element name="name"><xsl:value-of select="name"/></xsl:element>
        <xsl:element name="mail"><xsl:value-of select="mail"/></xsl:element>
      </xsl:element>
    </xsl:for-each>
  </xsl:element>
</xsl:template>

Or better still, do this, as xsl:element is not really needed here if you are using static names

<xsl:template match="/">
  <getGenResponse>
    <xsl:for-each select="//soap:Body/multiRef">
      <getGenReturn>
        <name><xsl:value-of select="name"/></name>
        <mail><xsl:value-of select="mail"/></mail>
      </getGenReturn>
    </xsl:for-each>
  </getGenResponse>
</xsl:template>

Note, you don't actually need the identity template in this case. Try this XSLT:

<xsl:stylesheet version="1.0" xmlns:response="http://tempuri.org/" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="soap response">

    <!-- Output -->
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
      <getGenResponse>
        <xsl:for-each select="//soap:Body/multiRef">
          <getGenReturn>
            <name><xsl:value-of select="name"/></name>
            <mail><xsl:value-of select="mail"/></mail>
          </getGenReturn>
        </xsl:for-each>
      </getGenResponse>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 1

Sateesh
Sateesh

Reputation: 53

<xsl:stylesheet version="1.0" xmlns:response="http://tempuri.org/" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="soap response">

    <!-- Output -->
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">

        <getGenResponse>
        <xsl:for-each select="//soap:Body/multiRef">
          <getGenReturn>
            <name><xsl:value-of select="name"/></name>
            <mail><xsl:value-of select="mail"/></mail>
          </getGenReturn>
         </xsl:for-each>
        </getGenResponse>

    </xsl:template>
</xsl:stylesheet>

Upvotes: 0

Related Questions