0

i wish change the xml into desire format. For that i am using xslt and my request xml is like this

REQUEST

 <?xml version="1.0" encoding="UTF-8" ?>
    <usersCollection xmlns="http://ws.wso2.org/dataservice">
        <users>
            <username>1</username>
            <password>2</password>
        </users>
        <users>
            <username>faisal</username>
            <password>sps123</password>
        </users>
        <users>
            <username>youtility</username>
            <password>sps123</password>
        </users>
        <users>
            <username>yout</username>
            <password>sp3</password>
        </users>
</usersCollection>

and my desire format is look like this

RESPONSE

<ns:getResponse xmlns:ns="http://ws.wso2.org/dataservice">
   <ns:user>
      <ns:myname>1</ns:myname>
      <ns:pwd>2</ns:pwd>
   </ns:user>
   <ns:user>
      <ns:myname>faisal</ns:myname>
      <ns:pwd>sps123</ns:pwd>
   </ns:user>
   <ns:user>
      <ns:myname>youtility</ns:myname>
      <ns:pwd>sps123</ns:pwd>
   </ns:user>
   <ns:user>
      <ns:myname>yout</ns:myname>
      <ns:pwd>sp3</ns:pwd>
   </ns:user>
</ns:getResponse>

and i write xslt for this like below

 <xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fn="http://www.w3.org/2005/02/xpath-functions"
                xmlns:ns="http://ws.wso2.org/dataservice"
                exclude-result-prefixes="ns fn">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
    <xsl:template match="/">
        <xsl:apply-templates select="//ns:usersCollection"/>
    </xsl:template>

    <xsl:template match="//ns:usersCollection">
      <ns:getResponse  xmlns:ns="http://ws.wso2.org/dataservice">
        <xsl:for-each select="//ns:usersCollection/ns:users">  
          <ns:user>
            <ns:myname>
              <xsl:value-of select="//ns:usersCollection/ns:users/ns:username/."/>
            </ns:myname>
            <ns:pwd>
               <xsl:value-of select="//ns:usersCollection/ns:users/ns:password/."/>
            </ns:pwd>
          </ns:user>
        </xsl:for-each> 
       </ns:getResponse>
    </xsl:template>
</xsl:stylesheet>

but its not giving my desired format out put i think i am mistaking in selecting xpath elements how would i add single elements for this i am getting like this result

<ns:getResponse xmlns:ns="http://ws.wso2.org/dataservice">
   <ns:user>
      <ns:myname>1 faisal youtility yout</ns:myname>
      <ns:pwd>2 sps123 sps123 sp3</ns:pwd>
   </ns:user>
   <ns:user>
      <ns:myname>1 faisal youtility yout</ns:myname>
      <ns:pwd>2 sps123 sps123 sp3</ns:pwd>
   </ns:user>
   <ns:user>
      <ns:myname>1 faisal youtility yout</ns:myname>
      <ns:pwd>2 sps123 sps123 sp3</ns:pwd>
   </ns:user>
   <ns:user>
      <ns:myname>1 faisal youtility yout</ns:myname>
      <ns:pwd>2 sps123 sps123 sp3</ns:pwd>
   </ns:user>
</ns:getResponse>

thanks in advance how would i get as per my desire format

Community
  • 1
  • 1
faisal shaik
  • 160
  • 4
  • 22

1 Answers1

0

Use more separate templates to match the individual elements. In your case, there is no need to use an xsl:for-each.

Stylesheet

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:ns="http://ws.wso2.org/dataservice">

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/ns:usersCollection">
       <ns:getResponse>
         <xsl:apply-templates/>
       </ns:getResponse>
   </xsl:template>

   <xsl:template match="ns:users">
      <ns:user>
         <xsl:apply-templates/>
      </ns:user>
   </xsl:template>

   <xsl:template match="ns:username">
      <ns:myname>
         <xsl:apply-templates/>
      </ns:myname>
   </xsl:template>

   <xsl:template match="ns:password">
      <ns:pwd>
         <xsl:apply-templates/>
      </ns:pwd>
   </xsl:template>

</xsl:stylesheet>

Output

<?xml version="1.0" encoding="UTF-8"?>
<ns:getResponse xmlns:ns="http://ws.wso2.org/dataservice">
        <ns:user>
            <ns:myname>1</ns:myname>
            <ns:pwd>2</ns:pwd>
        </ns:user>
        <ns:user>
            <ns:myname>faisal</ns:myname>
            <ns:pwd>sps123</ns:pwd>
        </ns:user>
        <ns:user>
            <ns:myname>youtility</ns:myname>
            <ns:pwd>sps123</ns:pwd>
        </ns:user>
        <ns:user>
            <ns:myname>yout</ns:myname>
            <ns:pwd>sp3</ns:pwd>
        </ns:user>
</ns:getResponse>

Why your approach does not work

Actually, you're not far off. The problem with your approach is that you use // in an incorrect way. An expression like this:

<xsl:value-of select="//ns:usersCollection/ns:users/ns:username/."/>

selects all ns:username elements in your input XML document instead of just the one username that is concerned at this point.

Mathias Müller
  • 22,203
  • 13
  • 58
  • 75
  • when we will use the for-each my scenario is not applicable for that – faisal shaik Feb 03 '14 at 11:25
  • Good question. Please have a look at http://stackoverflow.com/questions/6342902/for-loops-vs-apply-templates and http://stackoverflow.com/questions/4460232/differences-between-for-each-and-templates-in-xsl – Mathias Müller Feb 03 '14 at 12:05