0

假设我有一个 xslt 样式表,如下所示:

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

这里的执行顺序是什么?是否保证全局变量 $foo 将在全局变量 $bar 之前计算?(如果它依赖于处理引擎,我使用的是 libxslt)。

4

4 回答 4

4

通常,评估的顺序是不能保证的,除非这种保证来自表达式的依赖关系。例如:

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

在这里,可以肯定的是,baz将在输出之前的某个时间点进行评估 - 可能仅在输出之前,可能在启动时,可能介于两者之间 - 并且foobar在之前评估baz- 但是评估的相对顺序foobar是没有定义的。

dummy是一个有趣的案例。它实际上并没有在任何地方使用,因此可以完全省略,但是,如果我对规范的理解是正确的,处理器仍然必须引发错误,就像它被评估一样。在这一点上它这样做并不重要,因为没有办法从 XSLT 内部判断 - 所以dummy将在执行期间的某个未指定的时刻进行评估(可能是它做的第一件事,或者已经生成了所有输出之后的最后一件事),但保证会导致转换失败并出现错误。

这都是关于 XSLT 和 XPath 1.0 的。在 2.0 中,它更加轻松——甚至根本不需要进行评估;如果处理器可以通过跳过某些表达式的求值来获得有效结果,否则它们会导致错误,则它具有这样做的一揽子权限。

于 2009-09-02T03:26:19.370 回答
0

根据我的经验,执行模板时变量始终可用。事实上,我已经根据模板之外的变量处理了模板。

于 2009-09-02T02:02:12.210 回答
0

在模板中,变量定义将按从上到下的顺序执行 ( foothen bar)

编辑[删除了不正确的语句]:正如 Pavel 解释的这里,XSLT 在这种情况下具有明确定义的行为,它规定了如何评估变量。特别是,以下测试用例说明了您所询问的行为。

一个好的测试用例可能是使一个变量依赖于另一个变量......例如

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

然后可能将变量打印到屏幕上。

顺序也可以颠倒(例如)

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

对于它的价值,我认为你的意思是你在帖子select中写的地方。value

编辑 1:由于 XSLT 中的变量是不可变的,并且由于执行函数不会产生副作用,因此顺序并不重要。特别是,在顺序很重要的情况下,唯一可能出现的情况是我的简单说明(您应该作为测试运行以确保),其中一个变量取决于另一个变量的值。

编辑 2:修复了示例“代码”中的错误

于 2009-09-02T02:11:35.223 回答
-1

我正在与 ajitomatix 合作解决这个问题,真正的问题是:在初始化之后,我们在任何模板之外都有一堆这些变量声明:

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

只有当我们确保之前调用了 init 函数时,函数 fun() 才会给出正确的结果。但是通过 gdb 中的断点,我发现顺序几乎是随机的。

于 2009-09-02T03:39:13.480 回答