Monday, August 8, 2011

Achieving “While” functionality in XSL using recursive custom template call


Few days before I came across one XSL transformation business requirement where an xml element of Input data is having  two sub elements named “NumberBlockVON” and “NumberBlockBIS” . Name of these two is mentioned by our business user.  “NumberBlockVON” will have a positive Integer value and same happens for “NumberBlockBIS” . Now the requirement was whatever value specified as “NumberBlockBIS” that will be treated in output xml as “the power of” the value specified for “NumberBlockVON” . It means in out put xml “NumberBlockVON” will pass as it is but the value for “NumberBlockBIS” will be replaced by the <NumberBlockVON> to the power of <NumberBlockBIS>.
&lt;PickPackShipCustomElement&gt; &lt;NumberBlockVON&gt;5&lt;/NumberBlockVON&gt; &lt;NumberBlockBIS&gt;6&lt;/NumberBlockBIS&gt; &lt;/PickPackShipCustomElement&gt;
Now if it is a java requirement we can finished it off easily by writing a looping construct with the limit from 0 to <NumberBlockBIS>, and multiply the <NumberBlockVON> that many times. But here the problem is XSL constructs can loop through xml nodes , but it can’t loop through from 0 to any other specific value with in a single xml node. So we cant depend on XSL given constructs.
We use a custom XSL template to achieve this and call the template recursively with tuned parameters.<NumberBlockVON> value and <NumberBlockBIS>value is passed as a parameter to the template.How we achieve this is explained below with code snippet.



&lt;xsl:templatename="whileImplTemplate"&gt;
&lt; !--parameter limit_var is used to hold value of NumberBlockBIS which is used as a power value
--&gt;
&lt;xsl:paramname="limit_var"/&gt;
&lt; !--parameter var is used to hold value of NumberBlockVON which is used as a base value
--&gt;
&lt;xsl:param name="var"/&gt;
&lt; !--parameter Outvar is used to hold output value 
--&gt;
&lt;xsl:param name="Outvar" select="1"/&gt; &lt;xsl:param name="count_index" select="0"/&gt; &lt;xsl:variable name="out_var" select="$Outvar"/&gt;
&lt; !--while logic Implementation
--&gt;
&lt;xsl:choose&gt;
&lt; !--Is limit achieved --&gt;
    &lt;xsl:when test="$count_index &lt; $limit_var"&gt;
&lt; !--recursive template call if limit does not achieved--
&gt;
&lt;xsl:call-template name="whileImplTemplate"&gt; &lt;xsl:with-param name="limit_var" select="$limit_var"/&gt; &lt;xsl:with-param name="var" select="$var"/&gt; &lt;xsl:with-param name="count_index" select="number($count_index)+1"/&gt; &lt;xsl:with-param name="Outvar" select="number($var)*number($out_var)"/&gt; &lt;/xsl:call-template&gt;
&lt; !-- End template --&gt;
&lt;/xsl:when&gt; &lt;xsl:otherwise&gt; &lt;xsl:value-of select="$out_var"/&gt;
&lt; !--If limit achieved then print value --&gt;
    &lt;/xsl:otherwise&gt;
  &lt;xsl:choose&gt;
&lt;/xsl:template&gt; 
As a result the output comes like below
&lt;PickPackElement&gt; &lt;NumberBlockVON&gt;5&lt;/NumberBlockVON&gt; &lt;NumberBlockBIS&gt;15625&lt;/NumberBlockBIS&gt; &lt;/PickPackElement&gt;