Thursday, April 25, 2013

Concat two xml values with XSLT



The use-case described in this blog-post,is there's an WSO2 ESB node setup to proxy an incoming message to a particular back-end endpoint. 
Before delivering the message to the back-end endpoint,from the ESB node itself,this incoming message need to processed and change its inside xml payload format.


For eg: Below is the incoming message


<?xml version="1.0" encoding="UTF-8"?>
<CinemaHall name="liberty">
<OwnerData>
<Name>John Smith</Name>
<openedDate>12/12/80</openedDate>
<quality>good</quality>
</OwnerData>
<CinemaHallData>
<rows>100</rows>
<seats>
<seat>50</seat>
<seat>60</seat>
</seats>
</CinemaHallData>
</CinemaHall>

This message need to be changed as  below;

<?xml version="1.0" encoding="UTF-8"?>
<CinemaHall name="liberty">
<OwnerData>
<Name>John Smith</Name>
<openedDate>12/12/80</openedDate>
<quality>good</quality>
</OwnerData>
<CinemaHallData>
<rows>100</rows>
<seats> 50,60 </seats>
</CinemaHallData>
</CinemaHall>



Note I have highlighted which part of the payload need to be changed. So how to do that change. Simply you can use XSLT[XSL Transformations] support here.XSL means XSL stands for EXtensible Stylesheet Language, and is a style sheet language for XML documents.Simply to do a XSLT transformation from ESB,you can use the support of in-built XSLT mediator in it. Additionally you will a XSL stylesheet which contains the conversion source logic apart from incoming XML payload.

In the above example conversion,you'll see there are multiple XML elements called <seat> in the XML input payload and thus,you need to iterate through each <seat> element and get each value of it and concat those values with a ',' at each iteration.And specially appending of ',' need to avoid in last iterated <seat>  value.
Thus xsl sheet would contain,a for loop and if-else condition as the conversion source.
In XSLT world for loop => < xsl:for-each> &lt/xsl:for-each>   and if-else condition =>< xsl:choose>  < xsl:when> < /xsl:when> <xsl:choose> 

And the sample xsl sheet source for above conversion is as below;


<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

  <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="//CinemaHall/CinemaHallData/seats">
    <seats>
   <xsl:for-each select="//CinemaHall/CinemaHallData/seats/seat">
        <xsl:variable name="i" select="position()" />  
     <xsl:choose>
     <xsl:when test="count(//CinemaHall/CinemaHallData/seats/seat)-position() >=1">      
         <xsl:value-of select="concat(//CinemaHall/CinemaHallData/seats/seat[$i] , ',')"/>
      </xsl:when>
      <xsl:when test="count(//CinemaHall/CinemaHallData/seats/seat)-position() =0">      
        <xsl:value-of select="//CinemaHall/CinemaHallData/seats/seat[$i]"/>
      </xsl:when>
   </xsl:choose>
    </xsl:for-each> 
   </seats> 
    </xsl:template>

</xsl:stylesheet>


Note to test,my XSL sheet correctness,I used online provided XSLT tool support.





1 comment:

  1. Hi, nice description about Concating two xml values with XSLT .Thanks for your help..

    -Aparna
    Theosoft

    ReplyDelete