你可以模拟在XSLT一个布尔标志?(Can you simulate a boolean flag

2019-10-21 03:52发布

我想在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>

任何技巧都非常赞赏。

Answer 1:

不是真的...至少不是在你试图做到这一点的意义。 在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>


Answer 2:

有这样做的很多方面。 例如:

  • 您可以使用条件结构类似的xsl:如果/ XSL:选择。
  • 您可以使用变量来存储无论是从foo的计算并把它作为参数上栏应用模板。

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

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


Answer 3:

如果模板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; }
}


Answer 4:

这将使用你在你的问题中提到的方法:传递参数,从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>


文章来源: Can you simulate a boolean flag in XSLT?
标签: xslt