tags:

views:

172

answers:

4

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

A: 

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.

ChaosPandion
A: 

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"

Mark E
It's actually well-defined in XSLT; from 1.0 spec: "If the template or expression specifying the value of a global variable x references a global variable y, then the value for y must be computed before the value of x. It is an error if it is impossible to do this for all global variable definitions; in other words, it is an error if the definitions are circular."
Pavel Minaev
Thanks Mark. Please see my comment on Pavel's answer about why the dependent variable approach is not practical for me.
ajitomatix
+3  A: 

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.

Pavel Minaev
Thanks Pavel. I did think about creating dependency chain to guarantee order of execution. However it is impractical for our use case for the following reasons:1. There might be a lot of 'bar's depending on 'foo'. It's tedious to have every one of them depend on 'foo'.2. The 'foo' and 'bar' here are elements/functions provided by an xslt extension. Expecting users of the extension to always specifiy correct dependencies is somewhat error prone.
ajitomatix
Why do you need to guarantee any particular order of execution in the first place? You shouldn't be using any custom functions with side effects in XSLT anyway, and that's the only case where you would be able to observe the difference. If you need side effects, XSLT is a wrong choice to begin with.
Pavel Minaev
We need it so that we can let the user set some extension defaults which will then be used by the functions provided in the extension. Yes we can expect that the user has to pass in those values as parameters to every function call, but that becomes tedious quickly.
ajitomatix
You can have the user describe all your parameters as one XML tree. Then, he can assign the tree to a variable, and use that variable in further function calls.
Pavel Minaev
A: 

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.

Joy Dutta
Thanks for chipping in jdutta78.
ajitomatix