Reputation: 11939
What can I do to make this code work?
<xsl:choose>
<xsl:when test='type = 6'>
<xsl:variable name='title' select='root/info/title' />
</xsl:when>
<xsl:when test='type = 7'>
<xsl:variable name='title' select='root/name' />
</xsl:when>
<xsl:otherwise>
<xsl:variable name='title'>unknown</xsl:variable>
</xsl:otherwise>
</xsl:choose>
<div class='title'>
<xsl:value-of select='$title'/>
</div>
This doesn't work because when i do <xsl:value-of select='$title'/>
, $title
is out of scope. I tried to add the line <xsl:variable name='title'/>
outside of the scope, but that won't work either, because then when i call <xsl:variable name='title' select='root/info/title' />
for example, i already have set this variable before. How should I solve this?
Upvotes: 24
Views: 71094
Reputation: 107
Yes, you can do that in xlst 2.0, but it's forbidden in xlst 1.0 version.
the code following can run well in my pc with xslt processor saxson-he 9.8.0.12 .
<?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(go) is <xsl:sequence select="$map1?go"/>
map1(hello) is <xsl:sequence select="$map1?hello"/>
</xsl:template>
</xsl:stylesheet>
reslut of output is that:
v1 is: 123 v1 is: abcd v1 is: 234.5 map1(haha) is 119 map1(go) is 122 map1(hello) is 999
In xslt 1.0, it need recursion function, then pass the value as param.
Upvotes: -1
Reputation: 1
I'm doing it to save local value to xml xsl:desult
_document to folder /temp_variables_loop/loop-data-id_(position()).xml
.
And in next loop I read files from /temp_variables_loop.alias/loop-data-id_(position()-1).xml
.
You need to cheat xsl engine by make alias of /temp_variables_loop
to temp_variables_loop.alias
because you cannot read and write to the same file in one xsl.
Upvotes: -1
Reputation: 176219
You can't re-assign variables in XSLT (1.0). The name is probably not luckily chosen; an xsl:variable
is more a symbol than a variable.
In your sample you can use the following:
<xsl:variable name='title'>
<xsl:choose>
<xsl:when test='type = 6'>
<xsl:value-of select='root/info/title' />
</xsl:when>
<xsl:when test='type = 7'>
<xsl:value-of select='root/name' />
</xsl:when>
<xsl:otherwise>
<xsl:text>unknown</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Upvotes: 4
Reputation:
Besides @carolclarinet's standar answer and more compact @Dimitre's answer, when the result depend on some node and you are worry about reuse and extensibility, you can apply templates and use pattern matching, i.e:
<xsl:variable name="title">
<xsl:apply-templates select="type" mode="title"/>
</xsl:variable>
<xsl:template match="type[.=6]" mode="title">
<xsl:value-of select='../root/info/title"/>
</xsl:template>
<xsl:template match="type[.=7]" mode="title">
<xsl:value-of select='../root/name"/>
</xsl:template>
<xsl:template match="type" mode="title">
<xsl:text>unknown</xsl:text>
</xsl:template>
Upvotes: 2
Reputation: 243529
<xsl:choose> <xsl:when test='type = 6'> <xsl:variable name='title' select='root/info/title' /> </xsl:when> <xsl:when test='type = 7'> <xsl:variable name='title' select='root/name' /> </xsl:when> <xsl:otherwise> <xsl:variable name='title'>unknown</xsl:variable> </xsl:otherwise> </xsl:choose> <div class='title'> <xsl:value-of select='$title'/> </div>
This doesn't work
This is a FAQ:
You are defining several variables, each named $title
and each useless, because it goes out of scope immediately.
The proper way in XSLT 1.0 to define a variable based on conditions is:
<xsl:variable name="vTitle">
<xsl:choose>
<xsl:when test='type = 6'>
<xsl:value-of select='root/info/title' />
</xsl:when>
<xsl:when test='type = 7'>
<xsl:value-of select='root/name' />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'unknown'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Another way of defining the same variable: In this particular case you want the variable to have a string value. This can be expressed in a more compact form:
<xsl:variable name="vTitle2" select=
"concat(root/info/title[current()/type=6],
root/name[current()/type=7],
substring('unknown', 1 div (type > 7 or not(type > 5)))
)
"/>
Finally, in XSLT 2.0 one can define such a variable even more conveniently:
<xsl:variable name="vTitle3" as="xs:string" select=
"if(type eq 6)
then root/info/title
else if(type eq 7)
then root/name
else 'unknown'
"/>
Upvotes: 15
Reputation: 7014
You can move the choose inside the setting of the variable, like this:
<xsl:variable name="title">
<xsl:choose>
<xsl:when test='type=6'>
<xsl:value-of select="root/info/title" />
</xsl:when>
...
</xsl:choose>
</xsl:variable>
<div class='title'>
<xsl:value-of select="$title" />
</div>
Upvotes: 36