我想在XSLT脚本来模拟一个标志。 我们的想法是为模板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>
任何技巧都非常赞赏。
不是真的...至少不是在你试图做到这一点的意义。 在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>
有这样做的很多方面。 例如:
- 您可以使用条件结构类似的xsl:如果/ XSL:选择。
- 您可以使用变量来存储无论是从foo的计算并把它作为参数上栏应用模板。
真正的XSLT方式是对子级来定义巴不同的模板 - 配合不同的foo的案件:
<xsl:template match="bar[../foo[@a='x']]">
...
</xsl:template>
<xsl:template match="bar[../foo[@a='y']]">
...
</xsl:template>
如果模板FOO应产生输出,使用输出为标志的任何解决方案将无法工作。 在这种情况下,如果您使用的是基于Java的XSLT处理器(如撒克逊或Xalan的),你可以使用可变的Java对象。
但是请注意,这有自己的苦衷。 变换下面给出使用全局标志,这可能不足以对所有用例。 我想实例化标志的模板BLA,并把它作为参数foo和酒吧,但我无法在Xalan的工作。 另外请注意,我调用Java二传手在一个xsl:value-of
,因为否则调用可能会被优化掉(见无法访问更新的Java对象从撒克逊XSLT处理器 )。
<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; }
}
这将使用你在你的问题中提到的方法:传递参数,从foo到酒吧。 注意:此假设是,这正是一个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>