Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
The first stage is to evaluate the sequence constructor contained in the
The way that the instructions in the sequence constructor are evaluated is described in the rules for each instruction; the items produced by each instruction are concatenated together (in the order in which the instructions appear in the stylesheet) to produce the final result sequence.
The instructions in a sequence constructor can be evaluated in any order, or in parallel, but their results must be assembled in the correct order on completion.
If the
use-attribute-sets
attribute is present it must be a whitespace-separated list of lexical QNames that identify named
The second stage of the process is to use the result sequence delivered by evaluating the sequence constructor (and the
use-attribute-sets
attribute if present) to create the content of the new element node. This process works as follows:
1.
If there are any atomic values in the sequence, they are converted to strings using the XPath casting rules.
2.
Any sequence of adjacent strings is converted to a single text node, using a single space as a separator between adjacent strings. This allows list-valued content to be constructed, for example where the schema for the result document requires the content of an element to be a sequence of integers.
3.
If there is a document node in the sequence, then it is replaced in the sequence by its children (document nodes in the data model are not constrained to represent well-formed XML documents, so this may produce an arbitrary sequence of elements, text nodes, comments, and processing instructions).
4.
Adjacent text nodes within the sequence are combined into a single text node,
without
any space separator, and zero-length text nodes are removed.
5.
Duplicate attribute nodes are removed. If several attributes in the sequence have the same name, all but the last are discarded.
6.
Duplicate namespace nodes are removed. If several namespace nodes in the sequence have the same name
and string-value
(that is, they bind the same namespace prefix to the same namespace URI), then all but one of them are discarded. It makes no difference which one is kept.
It is an error if the resulting sequence contains an attribute or namespace that is preceded by a node that is not an attribute or namespace node.
The reason for this rule is to allow the implementation the flexibility to generate the output as an XML file, without having to build the result tree in memory first. If attributes could be added at any time, the whole result tree would need to be kept in memory.
It's also an error if there are conflicting namespace nodes at this point, that is, two namespace nodes that bind the same prefix to different namespace URIs, or a namespace node that declares a default namespace when the element itself is not in any namespace.
In the third stage of the process, the attribute nodes in the sequence are attached to the new element as its attributes, the namespace nodes are attached as its namespaces, and the other nodes are attached as its children. Officially, this involves making a deep copy of each node: this is because nodes in the data model are immutable, so you cannot change the parent of an existing node. In practice, making a copy at this stage is very rarely necessary, because in most cases the node being attached has only just been created and will never be used independently of its new parent. The only case where it is necessary is where the result sequence contains references to existing nodes, which can be produced using the
In this situation, the result is exactly the same as if
When an element node appears in the result sequence and is copied to form a child of the newly constructed element, it also acquires copies of all the parent element's namespaces. Futhermore, these percolate down to all descendant elements, unless there's already a namespace present with a conflicting definition. This process is called namespace inheritance, and is discussed further on page 311. The process can be suppressed by setting
inherit-namespaces=“no”
on the parent element.
The fourth and final stage of the process is called
namespace fixup
. Conceptually, this is done after all the nodes produced by the sequence constructor have been added to the new element. In practice all the information needed to do namespace fixup is available once all the attributes and namespaces have been added, and a processor that serializes the result tree “on the fly” is likely to perform this operation at that stage, so that the start tag of the serialized element can be output as early as possible. Namespace fixup is described in the next section.
Namespace Fixup
Namespace fixup is applied to any element node as soon as its content has been constructed, whether the node is created using the
The namespace fixup process can do two things: it can add namespace nodes to the tree and it can change the prefixes allocated to element and attribute nodes. The specification isn't completely prescriptive, but it makes it fairly clear that the fixup process is expected to make the minimal changes necessary to ensure that all the consistency rules defined in XDM are satisfied. Typically, this will involve the following steps:
1.
Examine the prefixes used on the element node and its attributes, and check that they are consistent with each other and with the element's existing namespace nodes. If there are any conflicts, allocate different prefixes to some or all of the nodes. Note that existing namespace nodes will never be changed by this process (this is because there might be namespace-sensitive content that relies on these namespaces).
2.
For every prefix used on the element node or on one of its attributes, ensure that there is a namespace node that binds this prefix to the relevant namespace URI. This will only involve adding namespace nodes, never modifying or deleting them.
This process is described in conceptual terms and the real implementation might be very different. For example, a processor might not actually store real namespace nodes in respect of the namespaces used on the element and attribute names, but instead might create them only when they are actually referenced.
The processor does not attempt to create namespace nodes in respect of namespace-sensitive content appearing in element or attribute nodes. For example, if you write the attribute
xsi:type=“xs:integer”
, namespace fixup will ensure that there is a namespace node for the
xsi
namespace, but not for the
xs
namespace. There are a number of reasons for this: one is that the processor often has no way of knowing that the content is namespace-sensitive, because it's not declared as such in a schema. Another is that namespace fixup happens before schema validation, because schema validation will fail if the right namespace bindings don't already exist. So in such cases it's your responsibility, when creating namespace-sensitive content, to ensure that the namespaces are declared. This can always be achieved using the