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

<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 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>

Tags:

Xslt