[ACCEPTED]-xslt variable scope and its usage-xslt

Accepted answer
Score: 17

is there any way I can just declare global 17 variable then assign some value in first 16 for loop and use that variable in second 15 for loop?

The way to assign value to an xsl:variable (of course this is only initialization) from within an xsl:for-each, is to include the xsl:for-each in the body of the variable.

Here is a complete example:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
     <xsl:variable name="vMax">
       <xsl:for-each select="num">
        <xsl:sort data-type="number" order="descending"/>

        <xsl:if test="position() = 1">
         <xsl:value-of select="."/>
        </xsl:if>
       </xsl:for-each>
     </xsl:variable>

     Values close to the maximum:
<xsl:text/>

       <xsl:for-each select="num">
        <xsl:if test="not($vMax - . > 3) ">
         <xsl:value-of select="."/>
         <xsl:text>&#xA;</xsl:text>
        </xsl:if>
       </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the following XML document...

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

...it 14 first defines a vMax variable that gets its 13 value from the xsl:for-each contained in its body.

Then 12 the vMax variable is used in the second xsl:for-each to 11 output all numbers that are "close" to the 10 so computed maximum.

The wanted, correct result is produced:

     Values close to the maximum:
07
08
09
10

It is also possible to simulate "assigning" a variable with different values by using a recursively called named template and pass the "new value" as parameter to the called template.

Here is an example 9 showing this technique. Here we are calculating 8 the maximum of values, contained in nodes 7 of a node-set. Every time we access the 6 next node in the node-set, the current maximum 5 is compared to this value and if necessary 4 the new maximum becomes the value of the 3 next node. We then call the same template 2 recursively, passing as the value of the 1 current maximum the new maximum:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
  <xsl:call-template name="max">
    <xsl:with-param name="pList" select="*"/>
  </xsl:call-template>
 </xsl:template>

 <xsl:template name="max">
   <xsl:param name="pMax" select="-99999999"/>
   <xsl:param name="pList"/>

   <xsl:choose>
     <xsl:when test="$pList[1]">
       <xsl:variable name="vnewMax" select=
       "$pMax * ($pMax >= $pList[1])
       +
        $pList[1] * not($pMax >= $pList[1])
       "/>

       <xsl:call-template name="max">
        <xsl:with-param name="pMax" select="$vnewMax"/>
        <xsl:with-param name="pList" select="$pList[position() > 1]"/>
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="$pMax"/>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied to the same XML document (above), the wanted, correct result is produced:

10
Score: 0

xsl:for-each is not a loop in the sense for or foreach loops exist 8 in procedural languages so any question 7 talking about loops is difficult to understand 6 and more difficult to answer.

If you want 5 to use global variables in XSLT you can 4 do so but you would bind a value to the 3 variable where you declare it (i.e. globally), you 2 can't assign a value later on in a for-each as you 1 seem to want to do.

Score: 0
  1. you have written, 'XSL is a procedural lang' .. Well, its not. It is a Declarative Language ..
  2. Variable is assigned along with its declaration, variables don't change!
  3. Usually we follow recursive call for templates using call-template passing params to them .. (this works like recursive function calling with passing arguments in procedural languages)
    That is one method to handle counts and conditional looping etc ..

We would be happy to help you incase if 3 you mention the exact scenario with Sample 2 XML, and the output you are expecting out 1 of it :)

More Related questions