Thursday, May 9, 2013

Sorting xml based on a tag value

If we want to sort an xml based on a field's value, we can use the following approch

Say for e.g  This is the source xml



<?xml version="1.0" encoding="UTF-8"?>
<OrganizationList>
   <Organization>
      <Name>Bharath</Name>
      <System>automotive</System>
      <main>Y</main>
   </Organization>
   <Organization>
      <Name>ATP</Name>
      <System>supply</System>
      <main>N</main>
   </Organization>
   <Organization>
      <Name>BSNL</Name>
      <System>service</System>
      <main>Y</main>
   </Organization>
</OrganizationList>


If we want to sort the above xml based on the value of main tag we can use the following approach




<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" exclude-result-prefixes="xsl">
   <xsl:template match="node()">
      <xsl:copy>
         <xsl:apply-templates />
      </xsl:copy>
   </xsl:template>
   <xsl:template match="OrganizationList">
      <xsl:copy>
         <xsl:apply-templates>
            <xsl:sort order="descending" select="main" />
         </xsl:apply-templates>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>


The result will be as shown below



<?xml version="1.0" encoding="UTF-8"?>
<OrganizationList>
   <Organization>
      <Name>Bharath</Name>
      <System>automotive</System>
      <main>Y</main>
   </Organization>
   <Organization>
      <Name>BSNL</Name>
      <System>service</System>
      <main>Y</main>
   </Organization>
   <Organization>
      <Name>ATP</Name>
      <System>supply</System>
      <main>N</main>
   </Organization>
</OrganizationList>





xquery : increment index in for each loop

Unlike java we cannot increment a variable's value in xquery while using for loop.

Say for e.g if we declare the following count variable in xquery and try to use it in the mapping, it will never work as we expect

 let $count := 0
 for $record at $position in $collection/books
                    let $count :=  $count + 1

                    return
                     <ns1:books>
                        <ns1:name>{ $record/name }</ns1:name>
                        <ns1:sequence>{ $count) }</ns1:sequence>
</ns1:books>


Instead we can use the following approach.

While declaring the for loop also declare a position variable.

Use this position variable in the place of count as follows


 for $record at $position in $collection/books
                   return
                     <ns1:books>
                        <ns1:name>{ $record/name }</ns1:name>
                        <ns1:sequence>{ $position) }</ns1:sequence>
   </ns1:books>