我想在xslt脚本中模拟一个标志。这个想法是模板foo设置一个标志(或一个计数器变量,或任何东西),以便可以从模板栏访问它。 Bar不是从foo调用的,而是从公共父模板调用的(否则我会将参数传递给它)。结构是这样的:
<xsl:template match="bla">
<xsl:apply-templates select="foo"/> <!-- depending on the contents of foo... -->
<xsl:apply-templates select="bar"/> <!-- ... different things should happen in bar -->
</xsl:template>
非常感谢任何技巧。
答案 0 :(得分:4)
不是真的......至少在某种意义上你没有尝试这样做。 XSLT中的变量是不可变的,一旦为它们赋值,就无法更改它们,因此尝试多次调用foo来更改标志的值是行不通的。您可以尝试一些模式,这可能会完成您要执行的操作,例如:
<xsl:variable name="myFlag"><xsl:apply-templates select="foo" /></xsl:variable>
<xsl:template match="bla">
<xsl:apply-templates select="bar" /> <!-- Can use the value of $myFlag --.
</xsl:template>
如果构建模板foo以返回标志的值,那将会有效,但是,如果标志的值意味着随时间变化,那么唯一可以实现此目的的方法是将对foo的调用合并到栏模板。
<xsl:template match="bla">
<xsl:apply-templates select="bar"> />
</xsl:template>
<xsl:template match="bar">
<xsl:variable name="flag"><xsl:apply-templates name="foo" /></xsl:variable>
<xsl:if test="$flag=1">
</xsl:if>
</xsl:template>
答案 1 :(得分:1)
有很多方法可以做到这一点。例如:
真正的XSLT方式是为bar定义不同的模板 - 它们匹配不同的foo案例:
<xsl:template match="bar[../foo[@a='x']]">
...
</xsl:template>
<xsl:template match="bar[../foo[@a='y']]">
...
</xsl:template>
答案 2 :(得分:0)
如果模板foo将产生输出,则使用输出作为标志的任何解决方案将不起作用。在这种情况下,如果您使用的是基于Java的XSLT处理器(例如Saxon或Xalan),则可以使用可变Java对象。
但请注意,这有其自身的困难。下面给出的转换使用全局标志,这可能不足以满足所有用例。我想在bla模板中实例化该标志并将其作为参数传递给foo和bar,但我无法在Xalan中使用它。另请注意,我在xsl:value-of
中调用Java setter,因为否则调用可能会被优化掉(参见Cannot access updated Java object from Saxon XSLT processor)。
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myflag="java:mypackage.MyFlag">
<xsl:variable name="foo-flag" select="myflag:new()" />
<xsl:template match="bla">
<xsl:apply-templates select="foo"/> <!-- depending on the contents of foo... -->
<xsl:apply-templates select="bar"/> <!-- ... different things should happen in bar -->
</xsl:template>
<xsl:template match="foo">
<xsl:choose>
<xsl:when ...>
<xsl:value-of select="myflag:set($foo-flag, true())" />
...
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="myflag:set($foo-flag, false())" />
...
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="bar">
<xsl:choose>
<xsl:when test="myflag:get($foo-flag)">
...
</xsl:when>
<xsl:otherwise>
...
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:transform>
最基本版本中的MyFlag类只是一个可变的布尔包装器。
public class MyFlag {
private boolean flag;
public void set(boolean flag){
this.flag = flag;
}
public boolean get(){ return flag; }
}
答案 3 :(得分:0)
这使用您在问题中提到的方法:传递参数,从foo到bar。注意:这假定每个foo
下方只有一个bla
,否则每个bar
元素将永远或多次调用条形模板。
<xsl:template match="bla">
<xsl:apply-templates select="foo" />
</xsl:template>
<xsl:template match="foo">
...
<xsl:apply-templates select="../bar">
<xsl:with-param name="flag" select="..." />
</xsl:apply-templates />
</xsl:template>