0

in a xsl transformation i am using a bunch of if-statements to react on occourences of segments in a xml document. A for-each is not suitable in this situation.

Every time the if-statement is true 1 should be added to the counter (i_prop + 1) and a segemnt with the counter value should be added to the output. Like in the example below

BUT it seams that the variable can be modifyed in the if-statement but not in a "global" way. After the statement the variable has the inital value as befor the if-statement.

Is there a way to use the modifyed variable in the next if-statement. And why is xsl doing this sort of stuff?

XSL_INPUT:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<!-- Create variable -->
<xsl:variable name="i_prop" select="0"/>
<test><xsl:value-of select="$i_prop"/></test>

<!-- +1 global -->
<xsl:variable name="i_prop" select="$i_prop + 1"/>
<test><xsl:value-of select="$i_prop"/></test>
<!-- +1 global -->
<xsl:variable name="i_prop" select="$i_prop + 1"/>
<test><xsl:value-of select="$i_prop"/></test>

<!-- +1 in if | FALSE -->
<xsl:if test="'A' = 'X'"><testif1><xsl:value-of select="$i_prop"/></testif1></xsl:if>

<!-- +1 in if | TRUE -->
<xsl:if test="'A' != 'X'"><xsl:variable name="i_prop" select="$i_prop + 1"/><testif2><xsl:value-of select="$i_prop"/></testif2></xsl:if>
<!-- +1 in if | TRUE -->
<xsl:if test="'A' != 'X'"><xsl:variable name="i_prop" select="$i_prop + 1"/><testif3><xsl:value-of select="$i_prop"/></testif3></xsl:if>

<!-- +1 global -->
<xsl:variable name="i_prop" select="$i_prop + 1"/>
<test><xsl:value-of select="$i_prop"/></test>

<!-- +1 in if | TRUE -->
<xsl:if test="'A' != 'X'"><xsl:variable name="i_prop" select="$i_prop + 1"/><testif4><xsl:value-of select="$i_prop"/></testif4></xsl:if>
<!-- +1 in if | TRUE -->
<xsl:if test="'A' != 'X'"><xsl:variable name="i_prop" select="$i_prop + 1"/><testif5><xsl:value-of select="$i_prop"/></testif5></xsl:if>

</xsl:template>
</xsl:stylesheet>

OUTPUT:

<test>0</test>
<test>1</test>
<test>2</test>
<testif2>3</testif2>
<testif3>3</testif3>
<test>3</test>
<testif4>4</testif4>
<testif5>4</testif5>

expected:

<test>0</test>
<test>1</test>
<test>2</test>
<testif2>3</testif2>
<testif3>4</testif3>
<test>5</test>
<testif4>6</testif4>
<testif5>7</testif5>

Thanks

Matthias

1 Answers1

2

Variables are scoped to their parent element. When you redefine (or, more precisely, override) a variable within an xsl:if instruction, it exist only there. When you return to the top level, you will find the original global variable, unchanged.

Consider the following stylesheet:

XSLT 2.0

<xsl:stylesheet version="2.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="/">
    <results>
        <!-- initial variable -->
        <xsl:variable name="i_prop" select="0"/>

        <test name="global">
            <xsl:value-of select="$i_prop"/>
        </test>

        <!-- redefine -->
        <xsl:variable name="i_prop" select="$i_prop + 1"/>
        <test name="redefine-global">
            <xsl:value-of select="$i_prop"/>
        </test>

        <!-- conditional redefine -->
        <xsl:if test="true()">
            <xsl:variable name="i_prop" select="$i_prop + 1"/>

            <test name="scoped to xsl:if">
                <xsl:value-of select="$i_prop"/>
            </test>
        </xsl:if>

        <test name="back to global">
            <xsl:value-of select="$i_prop"/>
        </test>
    </results>
</xsl:template>

</xsl:stylesheet>

Result

<?xml version="1.0" encoding="UTF-8"?>
<results>
   <test name="global">0</test>
   <test name="redefine-global">1</test>
   <test name="scoped to xsl:if">2</test>
   <test name="back to global">1</test>
</results>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51