How to change or reassign a variable in XSLT?
Asked Answered
S

5

24

How can I reassign a value to a variable previously assigned? I need it to works like this:

<xsl:variable name="variable2" select="'N'" />
....
<xsl:when test="@tip = '2' and $variable2 != 'Y'">                                                   
    <xsl:variable name="variable2" select="'Y'" />
</xsl:when>
Spumescent answered 8/10, 2013 at 18:9 Comment(0)
J
26

Variables in XSLT may only be assigned a value once. This is done by design. See Why Functional languages? for an appreciation of the motivation in general.

Rather than reassign a variable, write conditionals against the input document directly, or call a function (or named template) recursively with varying local parameters.

Anything you need to do can be done with an approach that does not require reassignment of variables. To receive a more specific answer, provide a more specific question.

See also:

Jerboa answered 8/10, 2013 at 18:55 Comment(0)
M
11

Just use multiple variables. Here's your example made to work...

    <xsl:variable name="variable1" select="'N'" />
    ....
    <xsl:variable name="variable2">
        <xsl:choose>
            <xsl:when test="@tip = '2' and $variable1 != 'Y'">
                <xsl:value-of select="'Y'" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$variable1" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
Mnemonic answered 14/4, 2016 at 16:14 Comment(0)
P
5

You cannot - 'variables' in XSLT are actually more like constants in other languages, they cannot change value.

Paisley answered 8/10, 2013 at 18:23 Comment(0)
T
0

Reassignable variables can be declared using an accumulator, available from XSLT version 3.0. :

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="3.0" >
      <xsl:mode use-accumulators="variable2" streamable="no"/>
      <xsl:output omit-xml-declaration="no" indent="yes"/>

      <xsl:accumulator name="variable2" initial-value="'N'">
       <xsl:accumulator-rule match="Inpayment" select="if ($value = 'N' and @tip = '2') then 'Y' else 'N' "/>
      </xsl:accumulator>

      <xsl:template match="node()|@*">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:template>

      <xsl:template match="Inpayment">
        <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:value-of select="accumulator-before('variable2')"/>
          <xsl:apply-templates select="node()"/>
        </xsl:copy>
      </xsl:template>

    </xsl:stylesheet>
Tenorite answered 27/9, 2017 at 11:7 Comment(0)
F
-3

I just almost believe the viewpoint in other replies before I test. It can really run well like that. xslt processor is saxon-he 9.8.0.12

my code :

        <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    exclude-result-prefixes="xs map"
    version="2.0">

    <xsl:template match="/">
        <xsl:variable name="i1" select="123" as="xs:integer"/>
        <xsl:variable name="s1" select="'abcd'" as="xs:string"/>
        <xsl:variable name="d1" select="234.5" as="xs:float"/>

        <!-- we test that variable v1 can be assignment multi times and it is ok.  -->
        <xsl:variable name="v1" select="$i1"/>
        v1 is: <xsl:value-of select="$v1"/>
        <xsl:variable name="v1" select="$s1"/>
        v1 is: <xsl:value-of select="$v1"/>
        <xsl:variable name="v1" select="$d1"/>
        v1 is: <xsl:value-of select="$v1"/>

        <xsl:variable name="map1" select="map{'haha':119, 'good':110}"/>
        <xsl:variable name="map2" select="map:put($map1, 'go', 122)"/>
        <xsl:variable name="map1" select="map:put($map2, 'hello', 999)"/>
        map1(haha) is <xsl:sequence select="$map1?haha"/>
        map1(hello) is <xsl:sequence select="$map1?hello"/>
    </xsl:template>

</xsl:stylesheet>

the result screenshort of the running

as your question, you can do like that:

<xsl:variable name="variable2" select="'N'" />
<xsl:variable name="variable2" select="hello:func1()" />

<xsl:function name="hello:func1" as="xl:string">
    .....
    <xsl:when test="@tip = '2' and $variable2 != 'Y'">                                                   
        <xsl:value-of select="'Y'" />
    </xsl:when>
</xsl:function>
Froehlich answered 2/12, 2019 at 1:52 Comment(3)
note that the xslt processor must surpport xslt 2.0 above.Froehlich
This is misunderstanding both the question and what's happening in your test. See my comment to your other post with the same claim: #18637719Low
@michael.hor257k, I have append some words in my answer. "as your question, you can do like that:....."Froehlich

© 2022 - 2024 — McMap. All rights reserved.