Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
This shows more explicitly how the sequence constructor contained in the
If you expand the variable definition in this way, you can also use the attributes
validation
and
type
on the
Another way of creating temporary documents is by copying an existing document node using either of the instructions
validation
and
type
attributes, and when the instructions are used to copy a document node, these attributes work the same way as the corresponding attributes on the
Because a temporary document exists only locally within your stylesheet, it sometimes makes sense to validate it using a schema that is also local to the stylesheet. To this end, XSLT allows you to write a schema document inline as the content of the
…
then the
xmlns:m=“http://www.acme.com/ns/local/months”>
For the complete stylesheet, see
inline.xsl
in the download files for this chapter. If you use inline schema documents, it's good practice to use a unique namespace, to ensure that the schema definitions don't conflict with any other schema definitions that might be loaded.
Validating Individual Elements
Rather than applying validation at the document level, it is possible to invoke validation of specific elements as they are constructed. This can be useful in a number of circumstances:
The usual way of creating a new element node in XSLT is either by using a literal result element or by using the
The
validation
and
type
, which work in a very similar way to the corresponding attributes of
The same facilities are available with literal result elements. In this case, however, the attributes are named
xsl:validation
and
xsl:type
. This is to avoid any possible conflict with attributes that you want copied to the result document as attributes of the element you are creating.
For example, suppose you want to validate an address. If there is a global element declaration with the name
address
, you might write:
If this matches the schema definition of the element declaration for
address
, this will succeed, and the resulting element will be annotated as an address—or more strictly, as an instance of the type associated with the address element, which might be either a named type in the schema, or an anonymous type. In addition, the child elements will also have type annotations based on the way they are defined in the schema, for example the
xs:integer
. If validation fails, the whole transformation is aborted.
What if there is no global element declaration for the
element (typically because it is defined in the schema as a local element declaration within some larger element)? You can still request validation if the element is defined in the schema to have a named type. For example, if the element is declared as:
then you can cause it to be validated by writing:
If neither a top-level element declaration nor a top-level type definition is available, you can't invoke validation at this level. The only thing you can do is either:
You don't need to invoke validation at more than one level, and it may be inefficient to do so. Asking for validation of
in the above example will automatically invoke validation of its child elements. If you also invoked validation of the child elements by writing, say:
…
then it's possible that the system would do the validation twice over. If you're lucky the optimizer will spot that this is unnecessary, but you could be incurring extra costs for no good reason.
If you ask for validation of a child element, but don't validate its parent element, then the child element will be checked for correctness, but the type annotation will probably not survive the process of tree construction. For example, suppose you write the following:
Specifying the
xsl:type
attribute on the
element is thus a sequence of four elements, of which the first has a type annotation of
xs:integer
. Evaluating the literal result element
creates a new
element, and forms children of this element from the result of evaluating the contained sequence constructor: The formal model is that the elements in this sequence are copied to form these children. The
xsl:validation
attribute on the
element determines what happens to the type annotations on these child elements. This defaults to either
preserve
or
strip
, depending on the
default-validation
attribute of the containing
strip
). If the value is
preserve
, the type annotation on the child element is preserved, and if the value is
strip
, then the type annotation on the child element is replaced by
xs:untyped
.
The type of an element never depends on the types of the items used to form its children. For example, suppose that the variable
$i
holds an integer value. Then you might suppose that the construct:
would create an element whose type annotation is
xs:integer
. It doesn't—the type annotation will be
xs:untyped
. Atomic values in the sequence produced by evaluating the sequence constructor are always (at least conceptually) converted to strings, and any type annotation in the new element is obtained by validating the resulting string values against the desired type.
This might not seem a very satisfactory design—why discard the type information? The working groups agonized over this question for months. The problem is that there are some cases like this one where retaining the type annotation obviously makes sense; there are many other cases, such as a sequence involving mixed content, where it obviously doesn't make sense; and there are further cases such as a sequence containing a mixture of integers and dates where it could make sense, but the definition would be very difficult. Because the working group found it difficult to devise a clear rule that separated the simple cases from the difficult or impossible ones, they eventually decided on this rather blunt rule: everything is reduced to a string before constructing the new node and validating it.
Note that when you use the
xsl:type
attribute to validate an element, the actual element name can be anything you like. There is no requirement that it should be an element name declared in the schema. It can even be an element name that is declared in the schema, but with a different type (though I can't see any justification for doing something quite so confusing, unless the types are closely related).
All the same considerations apply when creating a new element using the
validation
and
type
instead of
xsl:validation
and
xsl:type
.
The value of the
type
or
xsl:type
attribute is always a lexical QName, and this must always be the name of a top-level complex type or simple type defined in an imported schema. This isn't the same as the
as
attribute used in declaring the type of variables or functions. Note the following differences: