Recker Recker - 3 months ago 18
Perl Question

xsd:boolean in XSLT 1.0 vs XSLT 2.0

Based on first few lines of this answer, I infer that

<xsl:if test="not(@dothis) or @dothis=true()">


attribute
dothis
will be treated as node-set and not boolean value. Also, this value will always be true unless its not defined. However, I have observed that in XLST 2.0 transformation (using SAXON engine in JAVA), above condition gets satisfied and nodes such as following

<entry node="node1" dothis="false">Dr.Manhattan in rebirth!</entry>


are skipped appropriately.

However when I use XSLT 1.0 (using libxslt engine in Perl), I have to modify the condition as

<xsl:if test="not(@dothis) or (@dothis = 'true')">


and only then does the nodes like
node1
are skipped.

Why can't the Perl XSLT 1.0 engine understands
true()
correctly and needs the value as
'true'
explicitly?

Answer

Case 1

<xsl:if test="not(@dothis) or @dothis=true()">

Whether you are using XSLT 1.0 or 2.0, schema-aware or non-schema-aware, not(@dothis) returns true if and only if the attribute is absent. (In 2.0 terminology, not() uses the effective boolean value of its argument, and the effective boolean value of @dothis is true if the attribute exists, false if it is absent.)

By constrast, the value of @dothis=true() depends on the circumstances.

In XPath 1.0 you are comparing a node-set to a boolean, and the comparison is done by converting the node-set to a boolean - true if the attribute exists, false if not.

In XPath 2.0 in backwards compatibility mode (i.e. if the stylesheet specifies version='1.0') then it behaves like XPath 1.0.

In XPath 2.0 without BCM, with an untyped source document, the node-set @dothis is atomized. If the attribute is absent this produces an empty sequence and the comparison is false. If the attribute is present then the untypedAtomic value "true" or "false" is cast to the type of the other operand (xs:boolean), producing the value true() or false() respectively, so the expression returns true if the attribute is present with the value "true", and false if it is present with the value "false" or absent. (If it has any other value, e.g. "yes", you get an error).

In schema-aware XPath 2.0 without BCM, with a schema-validated source document, atomizing the attribute value produces either true() or false() or an empty sequence. This is compared with the boolean true(), and the effective result is the same as in the untyped case.

Case 2

<xsl:if test="not(@dothis) or (@dothis = 'true')">

The condition @dothis = 'true' is evaluated as follows:

In XPath 1.0 you are comparing a node-set to a string, and the comparison is done by converting the node-set to a string - true if the attribute exists and has the value "true", false otherwise.

In XPath 2.0 in backwards compatibility mode (i.e. if the stylesheet specifies version='1.0') then it behaves like XPath 1.0.

In XPath 2.0 without BCM, with an untyped source document, the node-set @dothis is atomized. If the attribute is absent this produces an empty sequence and the comparison is false. If the attribute is present then the untypedAtomic value "true" or "false" is cast to the type of the other operand (xs:string), producing the value "true" or "false" respectively, so the expression returns true if the attribute is present with the value "true", and false otherwise. (There is no error case).

In schema-aware XPath 2.0 without BCM, with a schema-validated source document, atomizing the attribute value produces either true() or false() or an empty sequence. If it's the empty sequence, the result is false. Otherwise, the boolean is compared with the string "true", and comparison of a boolean to a string always produces a type error.