XSLT 1.0含choose语句的布尔变量无法正确判定问题
在XSLT 1.0中正确创建和使用布尔变量
你遇到的核心问题是变量类型不匹配:你创建的processFlag是包含"true"/"false"字符串的结果树片段,并非布尔值。在XSLT 1.0中,boolean()函数判断结果树片段时,只要片段非空(哪怕内容是"false")都会返回true(),所以不管内部逻辑计算结果如何,test="boolean($processFlag)"永远为真,导致空内容的<box>被过滤。
解决方法
可以在XSLT 1.0中创建布尔变量,但必须通过select属性直接绑定布尔表达式,让变量的值是布尔原子值,而非结果树片段。
具体修改步骤
- 把
processFlag变量的定义从内容式改为select式,直接计算布尔结果,避免生成字符串。 - 在后续的
test条件中直接使用变量本身,无需额外的boolean()转换。
修改后的完整代码
<xsl:key name="myKey" match="box" use="local-name()"/> <xsl:variable name="allMustMatch" select="'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"/> <!-- 直接通过select绑定布尔表达式,生成布尔类型变量 --> <xsl:variable name="processFlag" select=" $allMustMatch != 'true' or ($allCount = $typeCount) "/> <xsl:template match="box"> <xsl:choose> <!-- 直接使用布尔变量,无需boolean() --> <xsl:when test="$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>
补充说明
如果逻辑更复杂,必须保留xsl:choose的写法,也可以通过字符串转布尔值的方式实现,但效率不如直接绑定布尔表达式:
<!-- 用choose生成字符串形式的布尔值 --> <xsl:variable name="processFlag"> <xsl:choose> <xsl:when test="$allMustMatch = 'true'"> <xsl:value-of select="$allCount = $typeCount"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="true()"/> </xsl:otherwise> </xsl:choose> </xsl:variable>
后续使用时通过字符串比较判断:
<xsl:when test="$processFlag = 'true'">
修改后,当$allCount = $typeCount的结果为false()时,processFlag会是false(),此时会走otherwise分支,保留所有<box>元素,与预期结果一致。
内容的提问来源于stack exchange,提问作者John Ernst
相关产品推荐
相关产品推荐

