使用具有 select 语句的变量作为布尔值

问题描述 投票:0回答:1

在 XSLT 1.0 中,我正在创建一个其中包含 select 语句的变量。这样做的目的是在变量中处理一次逻辑。然后使用该变量作为布尔下游一次或多次来控制逻辑流程。问题在于,无论变量内的逻辑计算结果为 true() 还是 false(),该变量在测试构造中始终计算结果为 true()。

那么,我可以通过这种方式创建一个布尔变量吗?如果是这样,我应该如何做并在下游使用它?

我的输入 XML 如下:

<root>
  <box id="435" type="A">keep</box>
  <box  id="872" type="A"></box>
  <box id="903" type="B">keep</box>
  <box id="1051" type="A">keep</box>
</root>

我的预期结果是一样的:

<root>
  <box id="435" type="A">keep</box>
  <box  id="872" type="A"></box>
  <box id="903" type="B">keep</box>
  <box id="1051" type="A">keep</box>
</root>

但我的实际结果是:

<root>
  <box id="435" type="A">keep</box>

  <box id="903" type="B">keep</box>
  <box id="1051" type="A">keep</box>
</root>

我的编程尝试是:

<xsl:key name = "myKey" match="box" use="local-name()"/>

<xsl:variable name="allMustMatch" select="'true'"/>

<xsl:variable name="processFlag">
  <xsl:choose>
    <xsl:when test="$allMustMatch = 'true'">
      <xsl:variable name="allCount" select="count(key('myKey', 'box'))"/>
      <xsl:variable name="typeCount" select="count(key('myKey', 'box')[not(@type = preceding::box/@type)]) + 1"/>
      <xsl:value-of select="$allCount = $typeCount"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="true()"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:template match="box">
  <xsl:choose>
    <!--  When $processFlag is false(), the following test evaluates to true().
          Also, when boolean($processFlag) is false(), the test evaluates to true(). 
          And when $processFlag is true() the test evaluates to true().
          How can I use $processFlag as a boolean? Or can I? -->
    <xsl:when test="boolean($processFlag)">
      <xsl:if test="normalize-space(.) != ''">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:if>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<!-- Identity template. -->
<xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
</xsl:template>
xslt xslt-1.0
1个回答
0
投票

考虑这个简单的例子:

<xsl:template match="/">
    <xsl:variable name="test">
        <xsl:value-of select="1=2"/>
    </xsl:variable>
    <xsl:value-of select="boolean($test)"/>
</xsl:template>

这里的结果将是

true
。为什么?因为根据定义,该变量包含一个字符串值为
"true"
的文本节点 - 并且任何长度非零的字符串都会被评估为
true

如果,OTOH,您将变量定义为:

<xsl:variable name="test" select="1=2"/>

那么变量会直接指向布尔值,结果会不同。


注意将变量定义为:

<xsl:variable name="allMustMatch" select="'true'"/>

还将变量绑定到字符串,并且这两个:

<xsl:variable name="allMustMatch" select="'false'"/>

将在布尔测试中评估为

true
。将变量绑定到布尔值的正确方法是:

<xsl:variable name="allMustMatch" select="true()"/>

或:

<xsl:variable name="allMustMatch" select="false()"/>

现在的问题是,当需要导出值时,如何将变量绑定到布尔值,例如通过使用

xsl:choose
。答案是不可能(在 XSLT 1.0 中)。你最多能做的就是:

<xsl:variable name="test">
    <xsl:choose>
        <xsl:when test="1=2">1</xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
</xsl:variable> 

然后,当您需要评估变量时,请执行以下操作:

<xsl:if test="number($test)">

但是,我不相信您的示例中需要如此复杂的构造。我不确定我是否遵循此处所需的逻辑,但您可能可以执行类似的操作(未经测试):

<xsl:variable name="allCount" select="count(key('myKey', 'box'))"/>
<xsl:variable name="typeCount" select="count(key('myKey', 'box')[not(@type = preceding::box/@type)]) + 1"/>
<xsl:variable name="processFlag" select="$allCount = $typeCount[$allMustMatch] + not($allMustMatch)">

这里的变量绑定到一个数字,在布尔测试中,如果为零,则计算结果为

false
,否则为
true

© www.soinside.com 2019 - 2024. All rights reserved.