Matching Parentless Nodes


In XSLT 1.0, every node belonged to a tree with a document node at its root. In fact, since the root was always the same kind of node, this kind of node was known as a root node rather than a document node. This has changed in XSLT 2.0: you can now have elements, or even attributes and text nodes, that have no parent. For example, if you write:

  <xsl:variable name="seq" as="element()*">   <e>2</e>   <f>5</f>   <g>9</g>   </xsl:variable>  

then the value of the variable $seq is a sequence of three element nodes. These element nodes have no parent, and they are therefore not siblings of each other. The XPath expression «$seq/e » will not select anything, because none of the three nodes in $seq has a child element whose name is «e » . If you want to select the «e » element, you should write «$seq[self::e] » .

A tree may thus be rooted at an element node rather than a document node, and this affects the rules for pattern matching. Two consequences of parentless elements complicate the rules.

The first consequence has to do with error handling. In XPath, using an expression such as «/ » or «//book » is an error if the context item is in a tree whose root is not a document node. The same applies to the id() and key() functions. This could mean that if you wrote <xsl:apply-templates select="$seq"/> , where $seq is a sequence of parentless elements, then as soon as the system tried to match it against a template rule specifying <xsl:template match="/"> , a runtime error would occur. This would happen, of course, only if the processor took the naive approach of matching every node against every pattern in the stylesheet, and even then only if it took the formal approach of evaluating the equivalent XPath expression. In practice, neither the user nor the implementer would be very happy if this was defined to be an error, so the specification includes a (very ad-hoc) rule saying that the system never attempts to match a parentless node against a pattern starting with «/ » or key() or id() , and therefore never hits this error condition.

More generally , runtime errors can also occur when evaluating a predicate in a pattern. For example, matching the pattern «//book[@price div 0 = 0] » could cause a runtime error (division by zero). The spec is open ended about these; it makes it clear that whether or not a particular error is ever reported will depend on the order in which the processor chooses to test the different patterns, and even then, on its evaluation strategy for a particular pattern.

The other problem that occurs with parentless nodes is that using the definition as we have it so far, the pattern «match="e" » means «match="child::e" » , and would match an <e> element only if it is a child of something. The Working Group decided that this would be just too confusing, and resolved that the pattern «e » should match every <e> element whether or not it has a parent. Similarly, «chapter/para » should match every <para> whose parent is a <chapter> , whether or not the <chapter> has a parent.

The way that the formal definition of patterns has been bent to meet this requirement is somewhat tortuous. It is done by introducing two new axes, child-or-top and attribute-or-top , and using these axes in the first step of a RelativePathPattern in place of the usual child and attribute axes. The child-or-top axis selects the children of the context node, unless the context node is a parentless element, text node, comment, or processing instruction, in which case it selects the parentless context node itself. Similarly, the attribute-or-top axis selects the context node itself if it is a parentless attribute node. Given these two extra axes, the equivalence between patterns and XPath expressions continues to hold. (These axes, of course, are purely notional. You can't use them explicitly either in an XPath expression or in a pattern.)

Note that this refinement does not apply to patterns starting with «/ » . The pattern «//book » , which in XSLT 1.0 matched exactly the same nodes as the pattern «book » , now has a slightly different meaning: it selects only <book> elements that are descendants of a document node. It will not select a parentless <book> element, or a <book> element in a tree whose root is a parentless element. This, incidentally, means that «match="//book" » is quite likely to be less efficient than «match="book" » , since the system now has to check what kind of node is at the root of the tree.




XSLT 2.0 Programmer's Reference
NetBeansв„ў IDE Field Guide: Developing Desktop, Web, Enterprise, and Mobile Applications (2nd Edition)
ISBN: 764569090
EAN: 2147483647
Year: 2003
Pages: 324

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net