Question

Lets say I have a xslt stylesheet like the following:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exslt="http://exslt.org/common"
    exclude-result-prefixes="exslt"
    version="1.0">

<xsl:output method="html" encoding="utf-8" indent="no" />
<xsl:variable name="foo" value="'foo'" />
<xsl:variable name="bar" value="'bar'" />

</xsl:stylesheet>

What is the order of execution here? Is it guaranteed that global variable $foo will evaluate before global variable $bar? (If it's dependent on the processing engine, I'm using libxslt).

Was it helpful?

Solution

The order of evaluation is, in general, not guaranteed except where such guarantees follow from dependencies of expressions. For example:

<xsl:variable name="foo" value="123" />

<xsl:variable name="bar" value="456" />

<xsl:variable name="baz" value="$foo + $bar" />

<xsl:variable name="dummy" value="42 div 0" />

<xsl:template match="/">
  <xsl:value-of select="$baz"/>
</xsl:template>

Here, it is certain that baz will get evaluated at some point prior to being output -maybe only immediately before being output, maybe at startup, maybe somewhere in between - and that foo and bar will be evaluated before baz - but the relative order of evaluation for foo and bar is not defined.

dummy is an interesting case. It's not actually used anywhere, and so could be omitted entirely, but, if my understanding of the spec is correct, the processor must nonetheless raise an error as if it was evaluated. At which point it does so is not important, because there's no way to tell from inside XSLT - so dummy will be evaluated at some unspecified moment during execution (could be the first thing it does, or the last after all output is already generated), but is guaranteed to cause the transformation to fail with an error.

This is all about XSLT and XPath 1.0. In 2.0, it is more relaxed - evaluation isn't even required to happen at all; if processor can obtain a valid result by skipping evaluation of some expressions where otherwise they would result in error, it has a blanket permission to do so.

OTHER TIPS

From my experience the variables are always available when the templates are executed. In fact I've processed templates based off of variables outside of templates.

Within a template the variable definitions will execute in top to bottom order (foo then bar)

Edit [incorrect statement removed]: As Pavel explains here, XSLT has well defined behavior in this case that stipulates how the variables will be evaluated. In particular, the following test cases illustrate the behavior you're asking about.

A good test case might be to make one variable depend on the other...e.g.

<xsl:variable name="foo" select="'foo'" />
<xsl:variable name="bar" select="$foo" />

Then maybe print the variables to screen.

The order can be inverted as well (e.g.)

<xsl:variable name="bar" select="$foo" />
<xsl:variable name="foo" select="'foo'" />

For what it's worth, I think you mean select where you wrote value in your post.

Edit 1: Since variables in XSLT are immutable and since executing functions can't have side effects the order shouldn't really matter. In particular, the only condition that could arise where the order matters is the one in my simple illustration (which you should run as a test to be sure) where one variable depends on the value of another.

Edit 2: fixed a goof in the example "code"

I am working with ajitomatix on this problem and the real issue is this: we have a bunch of these variable declarations outside of any templates, after an initialization:

<xsl:variable name="ignore" select="fun_init(args)" />
<xsl:variable name="foo1" select="fun('foo1')" />
<xsl:variable name="foo2" select="fun('foo2')" />
<xsl:variable name="foo3" select="fun('foo3')" />
...

The function fun() will give right result only if we make sure that the init function got called before. But through breakpoints in gdb I find the order is near random.

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