XSLT: Is the variable scope of <xsl:if> local?

Discussion in 'XML' started by Hoi Wong, Feb 20, 2008.

  1. Hoi Wong

    Hoi Wong Guest

    With the XSLT 1.0 engine that I was forced to use, I have to parse old XML
    scripts where the number (to be parsed and saved into $EPISODE_NUMBER_RAW)
    that I want to parse is written with a comma seperator if it goes beyond 3
    digits. i.e. the variable might be parsed as a string '1,324' or a number
    56, depending on which XML file I have.

    I was trying to get rid of the comma seperator by breaking the string into
    two parts (that number will never go beyond 5 digits), like this:


    <xsl:choose>
    <xsl:when test="contains($EPISODE_NUMBER_RAW, ',')">
    <xsl:variable name="EPISODE_NUMBER"
    select="concat(substring-before($EPISODE_NUMBER_RAW,','),
    substring-after($EPISODE_NUMBER_RAW, ',') )"/>
    </xsl:when>

    <xsl:eek:therwise>
    <xsl:variable name="EPISODE_NUMBER" select="$EPISODE_NUMBER_RAW"/>
    </xsl:eek:therwise>

    </xsl:choose>

    <xsl:value-of select="$EPISODE_NUMBER"/>


    However, the XSLT throws an error saying that $EPISODE_NUMBER is not found.
    Does <xsl:choose> has its own variable scope? If so, can anybody give me a
    pointer on how to solve the problem?

    Thanks a lot in advance.

    Cheers,
    Hoi
    Hoi Wong, Feb 20, 2008
    #1
    1. Advertising

  2. Hoi Wong

    Pavel Lepin Guest

    Hoi Wong <> wrote in
    <fpg62g$gg$>:
    > With the XSLT 1.0 engine that I was forced to use, I have
    > to parse old XML scripts where the number (to be parsed
    > and saved into $EPISODE_NUMBER_RAW) that I want to parse
    > is written with a comma seperator if it goes beyond 3
    > digits. i.e. the variable might be parsed as a string
    > '1,324' or a number 56, depending on which XML file I
    > have.
    >
    > I was trying to get rid of the comma seperator by breaking
    > the string into two parts (that number will never go
    > beyond 5 digits), like this:


    640K of memory will be enough for anybody.

    > <xsl:choose>
    > <xsl:when test="contains($EPISODE_NUMBER_RAW, ',')">
    > <xsl:variable name="EPISODE_NUMBER"
    > select="concat(substring-before($EPISODE_NUMBER_RAW,','),
    > substring-after($EPISODE_NUMBER_RAW, ',') )"/>
    > </xsl:when>
    > <xsl:eek:therwise>
    > <xsl:variable name="EPISODE_NUMBER"
    > select="$EPISODE_NUMBER_RAW"/>
    > </xsl:eek:therwise>
    > </xsl:choose>
    >
    > However, the XSLT throws an error saying that
    > $EPISODE_NUMBER is not found. Does <xsl:choose> has its
    > own variable scope? If so, can anybody give me a pointer
    > on how to solve the problem?


    Works:

    <xsl:variable name="number">
    <xsl:choose>
    <xsl:when test="contains($raw-number,',')">
    <xsl:value-of select=
    "
    concat(substring-before($raw-number,','),
    substring-after($raw-number,','))
    "/>
    </xsl:when>
    <xsl:eek:therwise>
    <xsl:value-of select="$raw-number"/>
    </xsl:eek:therwise>
    </xsl:choose>
    </xsl:variable>

    Better:

    <xsl:variable name="number"
    select="translate($raw-number,',','')"/>

    Even better - stuff it into a named template and invoke
    that. You never know when you might need this again.

    --
    When all you have is a transformation engine, everything
    looks like a tree.
    Pavel Lepin, Feb 20, 2008
    #2
    1. Advertising

  3. _All_ XSLT variable scopes are local.

    --
    Joe Kesselman / Beware the fury of a patient man. -- John Dryden
    Joseph Kesselman, Feb 20, 2008
    #3
  4. Hoi Wong

    Hoi Wong Guest

    translate() works perfectly! Thanks.



    "Pavel Lepin" <> wrote in message
    news:fpgmj8$16b$...
    >
    > Hoi Wong <> wrote in
    > <fpg62g$gg$>:
    >> With the XSLT 1.0 engine that I was forced to use, I have
    >> to parse old XML scripts where the number (to be parsed
    >> and saved into $EPISODE_NUMBER_RAW) that I want to parse
    >> is written with a comma seperator if it goes beyond 3
    >> digits. i.e. the variable might be parsed as a string
    >> '1,324' or a number 56, depending on which XML file I
    >> have.
    >>
    >> I was trying to get rid of the comma seperator by breaking
    >> the string into two parts (that number will never go
    >> beyond 5 digits), like this:

    >
    > 640K of memory will be enough for anybody.
    >
    >> <xsl:choose>
    >> <xsl:when test="contains($EPISODE_NUMBER_RAW, ',')">
    >> <xsl:variable name="EPISODE_NUMBER"
    >> select="concat(substring-before($EPISODE_NUMBER_RAW,','),
    >> substring-after($EPISODE_NUMBER_RAW, ',') )"/>
    >> </xsl:when>
    >> <xsl:eek:therwise>
    >> <xsl:variable name="EPISODE_NUMBER"
    >> select="$EPISODE_NUMBER_RAW"/>
    >> </xsl:eek:therwise>
    >> </xsl:choose>
    >>
    >> However, the XSLT throws an error saying that
    >> $EPISODE_NUMBER is not found. Does <xsl:choose> has its
    >> own variable scope? If so, can anybody give me a pointer
    >> on how to solve the problem?

    >
    > Works:
    >
    > <xsl:variable name="number">
    > <xsl:choose>
    > <xsl:when test="contains($raw-number,',')">
    > <xsl:value-of select=
    > "
    > concat(substring-before($raw-number,','),
    > substring-after($raw-number,','))
    > "/>
    > </xsl:when>
    > <xsl:eek:therwise>
    > <xsl:value-of select="$raw-number"/>
    > </xsl:eek:therwise>
    > </xsl:choose>
    > </xsl:variable>
    >
    > Better:
    >
    > <xsl:variable name="number"
    > select="translate($raw-number,',','')"/>
    >
    > Even better - stuff it into a named template and invoke
    > that. You never know when you might need this again.
    >
    > --
    > When all you have is a transformation engine, everything
    > looks like a tree.
    Hoi Wong, Feb 20, 2008
    #4
  5. Hoi Wong

    Pavel Lepin Guest

    Joseph Kesselman <> wrote in
    <47bc3401@kcnews01>:
    > _All_ XSLT variable scopes are local.


    Ah, but what about xsl:variable children of xsl:stylesheet
    element? Besides, I think it's not about lexical/dynamic
    scoping, but about what a variable's scope is. This is
    rarely if ever mentioned in tutorials, so you've got to
    shuffle through the spec to get a precise definition, and
    we all know how averse your J. Random Developer is to that.

    Yes, the scope of a local variable is limited by the nearest
    enclosing block in many of the modern languages. But XSLT
    doesn't really have blocks; and, say, PHP does not adhere
    to that convention. Compare:

    pavel@debian:~/dev/php$ a scope.pl
    use warnings; use strict;
    sub tst {
    my $foo = 1;
    if ($foo) {
    my $bar = 2;
    }
    print($foo . ' ' . $bar . "\n");
    }
    tst();
    pavel@debian:~/dev/php$ perl scope.pl
    Global symbol "$bar" requires explicit package name at
    scope.pl line 7.
    Execution of scope.pl aborted due to compilation errors.
    pavel@debian:~/dev/php$ a scope.php
    <?php error_reporting(E_ALL | E_STRICT);
    function tst() {
    $foo = 1;
    if ($foo) {
    $bar = 2;
    }
    print($foo . ' ' . $bar . "\n");
    }
    tst(); ?>
    pavel@debian:~/dev/php$ php scope.php
    1 2
    pavel@debian:~/dev/php$

    (Perl also has dynamic scoping, using which would produce
    the same behaviour as observed in the PHP script above -
    but the point is that in PHP, the scope of $bar is limited
    by the body of the function it's defined in, not by the
    nearest enclosing block.)

    I've also had some trouble with this in my first days with
    XSLT, so I can sort of sympathise with the OP.

    --
    When all you have is a transformation engine, everything
    looks like a tree.
    Pavel Lepin, Feb 21, 2008
    #5
  6. Pavel Lepin wrote:
    >>_All_ XSLT variable scopes are local.

    > Ah, but what about xsl:variable children of xsl:stylesheet
    > element?


    They're local to the stylesheet element and its content.

    > scoping, but about what a variable's scope is.


    A variable's lexical scope in XSLT -- the area within which that
    variable can be referenced by name -- is the xsl:variable element's
    following siblings and their descendants, unless the same name is used
    for another variable within that scope. Its dynamic scope is the
    execution of the element which encloses the xsl:variable element.

    Putting it another way: An XSLT variable is created at the xsl:variable
    element, is directly visible only within the element that element
    appears within.

    --
    Joe Kesselman / Beware the fury of a patient man. -- John Dryden
    Joseph Kesselman, Feb 21, 2008
    #6
  7. Hoi Wong

    Pavel Lepin Guest

    Joseph Kesselman <> wrote in
    <47bd9735$1@kcnews01>:
    > Pavel Lepin wrote:
    >>>_All_ XSLT variable scopes are local.

    >> Ah, but what about xsl:variable children of
    >> xsl:stylesheet element?

    >
    > They're local to the stylesheet element and its content.


    The spec seems to disagree [11.4]:

    A top-level variable-binding element declares a global
    variable that is visible everywhere.

    I believe this affects also affects imports and includes,
    but gotta test that on a real processor or shuffle through
    the spec some more to see if there's an explicit
    description of those cases.

    --
    When all you have is a transformation engine, everything
    looks like a tree.
    Pavel Lepin, Feb 21, 2008
    #7
  8. > I believe this affects also affects imports and includes,

    .... I think that's right. One can quibble about the details of how this
    interacts with import/include -- whether those "become part of the same
    stylesheet element" in some reasonable sense -- but I don't think it's
    worth debating.

    In practical terms, it's a difference that rarely, if ever, makes a
    difference.

    --
    Joe Kesselman / Beware the fury of a patient man. -- John Dryden
    Joseph Kesselman, Feb 21, 2008
    #8
  9. Hoi Wong

    P. Lepin Guest

    Joseph Kesselman wrote:
    >> I believe this affects also affects imports and includes,

    >
    > ... I think that's right. One can quibble about the details of how this
    > interacts with import/include -- whether those "become part of the same
    > stylesheet element" in some reasonable sense -- but I don't think it's
    > worth debating.
    >
    > In practical terms, it's a difference that rarely, if ever, makes a
    > difference.


    I apologise for displaying the symptoms of my Compulsive Nitpicking Syndrome
    in public yet again. :)

    --
    "These men died for us... frequently!"
    P. Lepin, Feb 21, 2008
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Xeon

    <xsl:variable> scope

    Xeon, Jul 1, 2003, in forum: XML
    Replies:
    1
    Views:
    13,723
    Marrow
    Jul 2, 2003
  2. Vijay singh
    Replies:
    1
    Views:
    428
    Martin Honnen
    Nov 4, 2004
  3. Replies:
    1
    Views:
    3,583
    A. Bolmarcich
    May 27, 2005
  4. David Filmer
    Replies:
    19
    Views:
    224
    Kevin Collins
    May 21, 2004
  5. Andrew Falanga
    Replies:
    2
    Views:
    191
    Andrew Falanga
    Nov 22, 2008
Loading...

Share This Page