Question

I am trying to use XSLT variables and not having much success, hopefully I'm just doing something dumb.

I have the following code snippet:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xalan="http://xml.apache.org/xslt"
  version="1.0">

    <xsl:template match="/">
      <xsl:variable name="config" select="query/@config"></xsl:variable>

so I expect there to be a variable 'config' set to the value of the 'config' attribute of my top-level element 'query'.

I then try to use the variable later in my stylesheet, for example:

<a href="localhost/test?go">
    {$config}
</a>

but the output I see in my output HTML document is:

<a href="localhost/test?go">
    {$config}
</a>

so the value has not been substituted as I would have expected.

I think this is pretty much the simplest case there could be, so I'm doing domething stupid! Please help, thanks!


UPDATE thanks to all who responded, I misunderstood the different contexts of whether I was working in an attribute or outside. Sorted my problem out nicely!

If I could I would accept two answers, the one I have, and @Aaron Digulla's, which explained the attributes thing.

Was it helpful?

Solution

In your stylesheet you must use:

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

instead of:

{$config}

OTHER TIPS

There are two questions here that seem the same, but which are subtly different: 1) How do I reference a variable by name? 2) Where can I reference a variable by name?

First, variables are always referenced using the $varname syntax. Second, this can be done anywhere an expression is allowed. It's the second part of this that seems to confuse. To start with, the value of an element or attribute will by default be output literally, so no variables are actually referenced in the following example:

<element attr="$test">$test or {$test}</element>

The output will literally match what was typed.

To output a variable's value, we need to reference it where an expression is allowed. In element content, we use xsl:value-of; in attributes that are treated as an Attribute Value Template (e.g. the attributes of a literal result element), expressions are delimited by curly braces {}. Assume the following declaration:

<xsl:variable name="test" select="'value'"/>

...then the following:

<element attr="{$test}"><xsl:value-of select="$test"/></element>

...results in:

<element attr="value">value</element>

A few parting notes on AVTs and value-of:

  • In both cases the variable was referenced as $test. The braces in an AVT are not part of the variable reference; they are expression delimiters.
  • In either case, the expression need not have contained a reference to a variable; any XPath expression would have been allowed.
  • Not all attributes in an XSLT document are treated as attribute value templates. For example, notice that xsl:value's select attribute already accepts an expression as content.
  • Question: Why can't you use value-of in an attribute, like this?

    <element attr="<xsl:value-of select="$test"/>"/>
    

    Answer: Because XSLT documents must contain well-formed XML (and that isn't).

  • Question: Why can't you use {$varname} in element content?

    Glib answer: because XSLT's creators didn't design it that way.

{$config} only works in attributes of XSLT elements. (Note: dollar inside the brace because the complete XPath expression must be surrounded by braces)

Use <xsl:value-of select="$config"/> instead of {$config}.

@lwburk's answer is great (+1), but the last question/answer is only accurate for XSLT 1.0 and 2.0. In 3.0 you can use a TVT (Text Value Template; similar to the AVT (Attribute Value Template) mentioned in @lwburk's answer).

To use a TVT, add the standard attribute xsl:expand-text="yes" to the element. This will cause the processor to treat descendant text nodes of that element as a TVT.

Example:

XSLT 3.0

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:template match="/">
        <xsl:variable name="who" select="'Dan'"/>
        <xsl:variable name="what" select="'BAM!'"/>
        <result xsl:expand-text="yes">This is {$who}'s result: {$what}</result>
    </xsl:template>

</xsl:stylesheet>

Output (using any well-formed XML as input)

<result>This is Dan's result: BAM!</result>

Note: Tested using Saxon-PE 9.5.

Because you need to use <xsl:value-of select="config"/> ?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top