WTF of the day...
Oct. 23rd, 2009 03:52 pmWhile you can use booleans all day long inside a template in XSLT 1.0, you can *NOT* pass them as values across template application or call boundaries. They invisibly become strings, leading to interesting things such as:
<xsl:template name="check_something">
flag? true
But if you change that true() in check_something to false(), you get...
flag? false
Why? Because value-of, the only way to transport a function value back out of the template, converts the boolean to a string. Either 'true' or 'false'. Which means in the second case, the string is 'false', leading to the correct output for the first line, has a boolean value of true (non-empty), which when not-ted, gives the *boolean* value on the second line, and when checked as a flag, is of course again true. Note complete lack of any differentiation in the output between the booleans and the strings.
You have to do an explicit check against the *STRING* 'true' at the call site. Change the xsl:if in the template to use test="$flag = 'true'" and it works as expected.
If you're expecting a really insane language model, that is.
<xsl:template name="check_something">
<xsl:value-of select="true()"/>
</xsl:template>
<xsl:template match="anElement">
<xsl:variable name="flag">
<xsl:call-template name="check_something"/>
</xsl:variable>
<xsl:message>flag? <xsl:value-of select="$flag"/></xsl:message>
<xsl:message>not(flag)? <xsl:value-of select="not($flag)"/></xsl:message>
<xsl:choose>
<xsl:when test="$flag">
<xsl:message>flag is true...</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:message>flag is false...</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
When check_something returns true, as above, then you get the following output:
flag? true
not(flag?) false
flag is true...
But if you change that true() in check_something to false(), you get...
flag? false
not(flag?) false
flag is true...
Why? Because value-of, the only way to transport a function value back out of the template, converts the boolean to a string. Either 'true' or 'false'. Which means in the second case, the string is 'false', leading to the correct output for the first line, has a boolean value of true (non-empty), which when not-ted, gives the *boolean* value on the second line, and when checked as a flag, is of course again true. Note complete lack of any differentiation in the output between the booleans and the strings.
You have to do an explicit check against the *STRING* 'true' at the call site. Change the xsl:if in the template to use test="$flag = 'true'" and it works as expected.
If you're expecting a really insane language model, that is.