XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition (34 page)

BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition
2.79Mb size Format: txt, pdf, ePub

Error Handling

There are two kinds of error that can occur during an XSLT transformation: static errors and dynamic errors. Static errors occur while the stylesheet is being compiled, and dynamic errors occur while the transformation is actually running. If you invoke the transformation using a single-shot interface that doesn't distinguish compilation from execution then you may not notice the difference, but it is there all the same.

XSLT 1.0 was designed to minimize the number of things that could cause runtime errors. This was done largely by defining fallback behavior. For example, if you supplied the string “Africa” as input to an arithmetic operator, you would get the result NaN (not-a-number). This might not be a very useful result, but the thinking was that it was better than producing a pop-up on the browser saying “Error in stylesheet.” For many runtime errors, implementors were in fact given a choice of reporting an error, or taking some defined fallback action.

The thinking in XSLT 2.0 has shifted significantly. There are now many more conditions that cause runtime errors, and most of these are not recoverable. There is also no try/catch mechanism to trap the errors when they occur: if a runtime error does occur in a stylesheet, it is fatal. In practice this means that you have to design your stylesheet to prevent them from occurring. This means that you have to test whether the input data is valid before using it in an operation that could cause errors if it isn't. For example, before trying to convert a string to an integer using the
xs:integer()
constructor function, it is a good idea to test whether the conversion is possible using a construct such as
if ($x castable as xs:integer) then …
.

Although the language specification is very precise about what constitutes an error and what doesn't, there may well be variations between processors as to whether runtime errors are actually reported in particular circumstances. This is partly because for some errors the choice of reporting the error or taking fallback action is still there, as in XSLT 1.0, and it is also because the order of execution of instructions (or of subexpressions within an XPath expression) is not precisely defined. Suppose you write an expression such as
exists(//employee[@retirement-date=current-date()])
(which finds out whether any employees are retiring today). One XSLT processor might find such an employee, and return
true
. Another might find an employee whose
retirement-date
attribute is not a date (perhaps it is the string
“unknown”
) and report a runtime error. Processors are never required to do extra work just to look for runtime errors. In this example, the processor is allowed to stop searching the employees as soon as it finds one that satisfies the required conditions.

What if there are no employees retiring today, and there are some employees whose retirement dates are not valid dates? Does the processor have to raise a runtime error, or can it return
false
? A straightforward reading of the specification suggests that it has to report an error in this case. However, the rules that allow the processor to devise an optimal execution strategy are drawn up so broadly that I think an implementor could argue that returning
false
was conformant.

Variables and Expressions

The system of data types lies at the core of any language, and the way expressions are used to compute values and assign these to variables is closely tied up with the type system. The XSLT type system interacts closely with XML Schema. We'll look in more detail in Chapter 4 at how stylesheets and schemas interact, and we'll survey the detailed repertoire of built-in types in Chapter 5. In this section, however, we'll assume some basic principles about types, and look at the way they are used in variables and expressions.

Variables

XSLT allows global variables to be defined, which are available throughout the whole stylesheet, as well as local variables, which are available only within a particular sequence constructor. The name and value of a variable are defined in an

element. For example:


This defines a variable whose name is
width
and whose value is the number
50
. The variable can subsequently be referenced in an XPath expression as
$width
. If the

element appears at the top level of the stylesheet (as a child of the

element), then it declares a global variable; if it appears within the body of an

or

element, then it defines a local variable.

The use of variables is superficially very similar to their use in conventional programming and scripting languages. They even have similar scoping rules. However, there is one key difference:
once a value has been given to a variable, it cannot be changed
. This difference has a profound impact on the way programs are written, so it is discussed in detail in the section
Programming without Assignment Statements
in Chapter 17, page 985.

The
as
attribute is optional, and defines the data type of the variable as being an integer. In this example, this doesn't add much: you can tell that it's an integer by looking at the value, and so can the XSLT processor. But there are cases where it's useful to specify the type. The
select
attribute doesn't have to be a constant, as it is in the previous example—it might, for example, be a call on a function. The
as
attribute acts both as an assertion about the type of the value (if the value is of the wrong type, you'll see an error message, either at compile time or at runtime) and also as a request to perform certain limited conversions from the supplied value to the specified type.

The type conversions that are possible in XSLT can be categorized as strong conversions and weak conversions. In a context like this, only weak conversions are applied. The weak conversions include the following:

  • Treating a value of type T as a value of a supertype of T, for example an
    xs:integer
    as an
    xs:decimal
    , or an
    xs:ID
    as an
    xs:string
    .
  • Extracting the typed value of a node, in cases where the supplied value is a reference to a node and the required type is atomic. This process is called
    atomization
    . The typed value of a node has the type determined by schema validation, for example if the node has been validated as an integer, you can use its value where an integer is expected, but not where (say) an
    xs:anyURI
    is expected. If there is no schema, then the typed value is the same as the string value.
  • Numeric promotion of an
    xs:integer
    or
    xs:decimal
    to an
    xs:float
    or
    xs:double
    , and of an
    xs:float
    to an
    xs:double
    . In XML Schema,
    xs:float
    is not defined as a subtype of
    xs:double
    , but XPath and XSLT behave largely as if it were.
  • Promotion of
    xs:anyURI
    values to
    xs:string
    . Again, XPath and XSLT behave largely as if
    xs:anyURI
    were a subtype of
    xs:string
    , even though XML Schema doesn't define it that way.
  • Conversion of untyped atomic values (which usually arise as the values of nodes in documents, or parts of documents, that have not been schema-validated) to the required type. This conversion uses the rules defined in XML Schema: for example, if the required type is
    xs:date
    , then the supplied value must have the correct lexical form for an
    xs:date
    , as defined in the XML Schema specifications (that is,
    YYYY-MM-DD
    with an optional timezone).

Other books

Run by Michaelbrent Collings
The Way Inn by Will Wiles
Trailer Trash by Sexton, Marie
The Last Place She'd Look by Schindler, Arlene
Last Resort by Susan Lewis
The Penwyth Curse by Catherine Coulter