开发者

XSLT: can I declare a variable globally and later assign a value to it

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'>
    &l开发者_如何学Got;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?


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>


<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'
 "/>


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>


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>


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜