Recipe 6.5. Avoiding 1.0 to 2.0 Porting Pitfalls
Problem
Not every 1.0 stylesheet will work
transparently
in 2.0.
Solution
If you need to port 1.0 stylesheets to 2.0, you will want to watch
out for several gotchas. Some of these problems can be eliminated by
using XSLT 1.0 compatibility mode; that is, by using
version=1.0 in the stylesheet element,
<xsl:stylesheet
version="1.0">. However, if you want to begin
migrating old stylesheets to 2.0, there are other solutions to these
incompatibilities, as explained next.
 |
XSLT 2.0 processors are not obligated to support backward
compatibility mode, although most probably will. If it is not
supported, the processor will signal an error.
|
|
Sequences do not transparently convert to atomic items
Consider the
fragment <xsl:value-of
select="substring-before(Name, ' ')"/>. What happens if
this is evaluated in a context that includes more than one
Name element? In XSLT 1.0, only the first one
would be used, and the rest would be ignored. However, XSLT 2.0 is
stricter and signals a type error because the first argument if
substring-before can only be a sequence of 0 or 1
strings.
To remedy this, you should get in the habit of writing
<xsl:value-of
select="substring-before(Name[1], ' ')"/>. On the
other hand, you may want to know about these errors because they
might signal a bug in the way the stylesheet or its input documents
are written. An alternative fix, which may be applicable in some
circumstances, is to combine multiple nodes into a single node before
presenting the sequence to a function expecting only one. For
example, <xsl:value-of
select="substring-before(string-join(Name), '
')"/> would not generate an error.
Types do not transparently convert to other types
XSLT 1.0 was very lax when it came to
type
conversions. If a function expected a number and you provided a
string, it would do its best to convert the string to a number and
visa versa. The same applied to conversions among Boolean and integer
or Boolean and string. The old behavior can be preserved by using 1.0
compatibility mode. However, you can also explicitly convert values:
<xsl:variable name="a" select=" '10' "/>
<xsl:value-of select="sum($a, 1)"/> <!-- Error -->
<xsl:value-of select="sum(number($a), 1)"/> <!-- OK -->
<xsl:value-of select="string-length(10)"/> <!-- Error -->
<xsl:value-of select="string-length(string(10))"/> <!-- OK -->
<xsl:value-of select="string-length(string(true( )))"/>
<!-- OK, equals 4 -->
<xsl:value-of select="1 + true( )"/> <!-- Error -->
<xsl:value-of select="1 + number(true( ))"/> <!-- OK, equals 2 -->
Extra parameters are not ignored
In XSLT 1.0, if you invoked a template with
xsl:call-template passed parameters that the
template did not define, the extra parameters were silently ignored.
In 2.0, this is an error. You can disable this error by using 1.0
compatibility mode. There is no other work around, except removing
the
extra parameters or introducing
defaults into the existing template.
Stricter semantic checking will cause errors on questionable usage
Examples of this can be seen in both the
xsl:number and xsl:template
instructions. If you use level and
value attributes together in
xsl:number, the level attribute
is ignored in 1.0, but this is an error in 2.0. Similarly, with
xsl:template, you cannot specify
priority or mode in 2.0, if
there is no match attribute defined.
Discussion
Use of
backward-compatibility
mode to correct errors in 1.0 stylesheets has other consequences. In
particular, it means that some things will behave differently. In 1.0
compatibility mode:
xsl:value-of will output only the first item of a
sequence rather than all items separated by spaces. an attribute value template (e.g. <foo
values="{foo}"/>) will output
only the first item of a sequence rather than all items separated by
spaces. the first number in a sequence will be output rather than all numbers
separated by spaces when using xsl:number. For these reasons, it would be wise not to rely on
backward-compatibility mode for new stylesheet development intended to
target a 2.0-compliant processor.
 |