Re: [xsl] update value of variable in for-each loop

Subject: Re: [xsl] update value of variable in for-each loop
From: David Rudel <fwqhgads@xxxxxxxxx>
Date: Wed, 9 Apr 2014 07:13:24 +0200
Henry,
Everything Mike and David has said is true, but I think the reason
this is not giving the output you expect may be based on a
misunderstanding about how for-each works and the nature of variable
declaration in XSLT.

Below I have pasted one part of your code:

       <xsl:variable name="foo">
                     <xsl:for-each select="data">
                         <xsl:choose>
                             <xsl:when test="contains(elements/
elementA '1234) or contains(elements/package/id '55) or
contains(elements/category/id, '67)" or contains(.............">

                                 <xsl:value-of select="1"/>
                             </xsl:when>
                             <xsl:otherwise>
                                 <xsl:value-of select="0"/>
                             </xsl:otherwise>
                         </xsl:choose>
                     </xsl:for-each>
                </xsl:variable>

Call this block "B"
I think you may be thinking of "B" as a type of procedure where "$foo"
is being defined. However, that is not quite true. "B" is not merely a
procedure in which you define $foo. Rather, this code fragment defines
$foo as the collection of all the things created by the  block.

In particular, B does not say "Look through the data nodes and if
*any* of them satisfy the test ["contains(elements/
elementA '1234) or contains(elements/package/id '55) or
contains(elements/category/id, '67)" or contains(............."], then assign
the value of "1" to B, otherwise assign "0."

Rather, what this code does is say "Create a temporary document in memory.
Go through every data node, testing each one separately. _Each_ time a
data element passes the test, write down a "1" (as a text node) in
this temporary document. _Each_ time a data element fails the test,
write down a "0" (as a text node).  Then assign the value of $foo to
be this entire temporary document.

Then later when you test the value of $foo, it atomizes this temporary
document into a string of the individual 1s and 0s.

Also, you shouldn't think of variables in XSLT the same way as you do
in other languages.

In most languages, you initialize a variable (I think this is what you
were doing with the empty instruction <xsl:variable name="foo"/> at
the top).  Then you change the variable as the program progresses.

Variables in XSLT are immutable. They cannot be changed. Once you
define a variable in a given scope, you should not redefine the same
variable in that scope. This is why David was saying that the
<xsl:variable name="foo"/> line served no purpose.

(Indeed, I'm surprised your processor did not raise a warning when you
defined $foo twice in the same scope.)

-David

On Tue, Apr 8, 2014 at 10:54 PM, David Carlisle <davidc@xxxxxxxxx> wrote:
> On 08/04/2014 21:49, henry human wrote:
>>
>> When I run this code the output of the variable foo is never 1 or 0
>> as I expect but either 0011 or 11 or 0001
>
>
> Yes, but the code clearly is going to make 000111 etc, because that's
> what it is coded to do. You have only shown the code. You _want_ it to
> do something else but you have not said what that is, you expect that we
> can tell from the code when you want it to be 1 and when you want it to
> be 0, but how can we guess that? We do know the input, or the desired
> output or the intention of the code block.
>
>
> David
>
> --
> google plus: https:/profiles.google.com/d.p.carlisle
>



-- 

"A false conclusion, once arrived at and widely accepted is not
dislodged easily, and the less it is understood, the more tenaciously
it is held." - Cantor's Law of Preservation of Ignorance.

Current Thread