2010-04-14 41 views
1

我想在xslt脚本中模拟一个标志。这个想法是为模板foo设置一个标志(或者一个计数器变量,或者其他任何东西),以便它可以从模板栏访问。 Bar不是从foo调用的,而是从一个共同的父模板中调用的(否则我会传递一个参数给它)。结构是这样的:你可以在XSLT中模拟布尔标志吗?

<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

请提供更多信息。问题严重不足。 – 2010-04-14 21:50:04

回答

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纳入条模板中。

<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

有很多方法可以做到这一点。例如:

  • 您可以使用像xsl:if/xsl:choose这样的条件结构。
  • 您可以使用变量来存储从foo计算的任何内容,并将其作为参数传递给bar上的apply-templates。

真正的XSLT方式是对子级来定义巴不同的模板 - 配合不同的foo的案件:

<xsl:template match="bar[../foo[@a='x']]"> 
    ... 
</xsl:template> 
<xsl:template match="bar[../foo[@a='y']]"> 
    ... 
</xsl:template> 
0

如果模板富应产生输出,使用输出为标志的任何解决方案将无法正常工作。在这种情况下,如果您使用的是基于Java的XSLT处理器(例如Saxon或Xalan),则可以使用可变的Java对象。

但请注意,这有它自己的困难。下面给出的转换使用全局标志,可能不足以满足所有用例。我想在bla模板中实例化标志并将其作为参数传递给foo和bar,但是我无法在Xalan中使用它。另请注意,我在xsl:value-of中调用了Java设置器,因为否则该调用可能会被优化掉(请参阅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; } 
} 
0

这使用您在问题中提到的方法:传递一个参数,从foo到bar。注意:这假定每个bla下面都有一个foo,否则每个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>