18 June 2001

1. Document Object Model XPath

Editors
Ray Whitmer, Netscape/AOL

Table of contents

1.1. Introduction

XPath is becoming an important part of a variety of many specifications including XForms, XPointer, XSL, CSS, and so on. It is also a clear advantage for user applications which use DOM to be able to use XPath expressions to locate nodes automatically and declaratively. But liveness issues have plagued each attempt to get a list of DOM nodes matching specific criteria, as would be expected for an XPath API. There have also traditionally been object model mismatches between DOM and XPath. This proposal specifies new interfaces and approaches to resolving these issues.

1.2. General considerations

This section considers the differences between the Document Object Model and the XPath Model as defined by [XPath 1.0] as well as Ranges.

1.2.1. Text Nodes

The XPath model sees a single logical text node where DOM may have multiple fragmented Text nodes due to cdata sections, entity references, etc. Instead of returning multiple nodes where XPath sees a single logical text node, only the first non-empty DOM Text node of any logical XPath text will be returned or entered into Node set. Applications will have to manually gather the text of a single logical text node from multiple nodes beginning with the first Text node identified by the implementation.

Note: DOM Level 3 Core adds the attribute wholeText on the Text interface for retrieving the whole text for logically-adjacent Text nodes.

1.2.2. Namespace Nodes

The XPath model expects namespace nodes for each in-scope namespace attached to each Element. DOM and certain other W3C infoset conformant implementations only maintain the declaration of namespaces instead of replicating them on each Element where they are in-scope. The DOM implementation of XPath will only return Attr nodes of in-scope namespace declarations, which may be attached to the current element or its ancestors.

Issue Namespace-1:
This does not exactly match the description of XPath 1.0. Need input from the XQuery 1.0/XPath 2.0 Data Model.
Issue Namespace-2:
How to represent namespace nodes in the Core?
Issue Namespace-3:
There is no declaration node corresponding to the always-present "xml" prefix declaration.
Issue Namespace-4:
The uniqueness and document order of namespace declaration nodes is different from in-scope namespace nodes, producing a different order and number of nodes in the result set where the namespaces nodes of multiple elements are requested.
Issue Namespace-5:
The ownerElement of the namespace declaration is different from the parent of in-scope namespace nodes of XPath.

1.2.2.1. Advantages

  • Most common use cases would just work.
  • No need to manufacture convenience nodes.
  • XPath can be used to find and manipulate namespace declarations that are invisible in the strict XPath model.
  • XQuery also models the namespace declaration instead of the in-scope namespace.

Note: The DOM WG should try to ensure compatibility between this approach and XPath 2.0. Removing the parent from XPath 2.0 namespace nodes does not help, because the relationship between the Namespace and Element was maintained, since XPath 2.0 maintains that the namespace nodes of an element still occur before its attribute nodes producing a many-to-one relationship between XPath 2.0 Namespace Nodes and DOM Attr nodes which declare namespaces, making it impossible to sort the results without a separate Namespace node for each occurrence to represent the order correctly. Also, the XQuery 1.0 and XPath 2.0 Data Model specification [XQuery 1.0 and XPath 2.0 Data Model] still maintains that each constructed Namespace node has a unique identity, implying that duplicates would be improperly eliminated in the resultant set. (See XQuery 1.0 and XPath 2.0 Data Model 3.1, 3.2, etc.).

1.2.3. Ranges

Since XPath returns nodes and strings, but never ranges, there is no use for ranges in this API as had been previously suggested. It is conceivable that in the future data types could be added supporting the notion of DOM ranges, especially if the DOM Working Group decided to do the work, at which time a range could become another return type of an XPath expression supported by the evaluator. This would be supportable by adding appropriate additional methods to XPathEvaluator to evaluate XPath expressions returning ranges.

If sets of ranges were introduced, an appropriate interface for sets of ranges would need to be added to DOM (needed anyway for implementation of multiple selection), and this would be another new return type supported by the XPath evaluator.

1.3. Interfaces

A DOM application may use the hasFeature(feature, version) method of the DOMImplementation interface with parameter values "XPath" and "3.0" (respectively) to determine whether or not the event module is supported by the implementation. In order to fully support this module, an implementation must also support the "Core" feature defined in the DOM Level 3 Core specification [DOM Level 3 Core]. Please, refer to additional information about conformance in the DOM Level 3 Core specification [DOM Level 3 Core].

Note: There is a fair amount of complexity in custom extension functions and variables because variables may be of various types and functions have arguments and return types. There are additional issues such as keeping functions from modifying the DOM, what exceptions to allow, and all the fun of callbacks. If the first draft of the specification ignores custom functions and variables, this should not make it more difficult to later add such a factory to the specification or for implementors to provide alternate evaluators that access extension functions and variables.

Definition group XPathExceptionCode
Defined Constants
TYPE_ERR
If an attempt is made to convert a XPath result into an imcompatible type.
Exception XPathException

IDL Definition
exception XPathException {
  unsigned short   code;
};

Interface XPathEvaluator

The evaluation of XPath expressions is available in XPathEvaluator. A Document which implements the XPath module will be castable using language-specific mechanisms to XPathEvaluator, which will provide evaluation of XPath expressions with no special extension functions or variables. XPathEvaluator implementations may be available from other sources that provide extension functions or variables.

Issue XPathEvaluator-1:
should we return an Object as the result instead and have one general evaluateAs method?

IDL Definition
interface XPathEvaluator {
  boolean            evaluateAsBoolean(in DOMString expression, 
                                       in Node contextNode, 
                                       in NamespaceResolver resolver)
                                        raises(XPathException);
  double             evaluateAsNumber(in DOMString expression, 
                                      in Node contextNode, 
                                      in NamespaceResolver resolver)
                                        raises(XPathException);
  DOMString          evaluateAsString(in DOMString expression, 
                                      in Node contextNode, 
                                      in NamespaceResolver resolver)
                                        raises(XPathException);
  Node               evaluateAsNode(in DOMString expression, 
                                    in Node contextNode, 
                                    in NamespaceResolver resolver)
                                        raises(XPathException);
  ActiveNodeSet      evaluateAsNodeSet(in DOMString expression, 
                                       in Node contextNode, 
                                       in NamespaceResolver resolver)
                                        raises(XPathException);
};

Methods
evaluateAsBoolean
Evaluates an XPath expression and converts the result to a boolean.
Parameters
expression of type DOMString
The XPath expression to be evaluated.
contextNode of type Node
The context node for the evaluation of the XPath expression.
resolver of type NamespaceResolver
The resolver permits translation of prefixes within the XPath expression into appropriate namespaceURIs.
Return Value

boolean

The result of the evaluation of the XPath expression.

Exceptions

XPathException

TYPE_ERR: Raised if the result cannot be converted to a boolean

evaluateAsNode
Evaluates an XPath expression and returns the first node of the resulting set, null if the resulting set is empty.
Parameters
expression of type DOMString
The XPath expression to be evaluated.
contextNode of type Node
The context node for the evaluation of the XPath expression.
resolver of type NamespaceResolver
The resolver permits translation of prefixes within the XPath expression into appropriate namespaceURIs.
Return Value

Node

The result of the evaluation of the XPath expression.

Exceptions

XPathException

TYPE_ERR: Raised if the result cannot be converted to a node set.

evaluateAsNodeSet
Evaluates an XPath expression and returns the result as a node set.
Parameters
expression of type DOMString
The XPath expression to be evaluated.
contextNode of type Node
The context node for the evaluation of the XPath expression.
resolver of type NamespaceResolver
The resolver permits translation of prefixes within the XPath expression into appropriate namespaceURIs.
Return Value

ActiveNodeSet

The result of the evaluation of the XPath expression.

Exceptions

XPathException

TYPE_ERR: Raised if the result cannot be converted to a node set.

evaluateAsNumber
Evaluates an XPath expression and converts the result to a number.
Parameters
expression of type DOMString
The XPath expression to be evaluated.
contextNode of type Node
The context node for the evaluation of the XPath expression.
resolver of type NamespaceResolver
The resolver permits translation of prefixes within the XPath expression into appropriate namespaceURIs.
Return Value

double

The result of the evaluation of the XPath expression.

Exceptions

XPathException

TYPE_ERR: Raised if the result cannot be converted to a number (IEEE double precision floating point value)

evaluateAsString
Evaluates an XPath expression and converts the result to a string.
Parameters
expression of type DOMString
The XPath expression to be evaluated.
contextNode of type Node
The context node for the evaluation of the XPath expression.
resolver of type NamespaceResolver
The resolver permits translation of prefixes within the XPath expression into appropriate namespaceURIs.
Return Value

DOMString

The result of the evaluation of the XPath expression.

Exceptions

XPathException

TYPE_ERR: Raised if the result cannot be converted to a DOMString

An XPath node set is represented by a NodeSet interface which maintains a set of references to nodes. No node is ever duplicated in NodeSet. When ActiveNodeSet is returned from an XPath evaluation, it corresponds to the hierarchy that it was requested on until the hierarchy is mutated in any way (anything that could produce a mutation event) at which time the set becomes invalid and any future call raises an exception. This permits the XPath sets to be computed either all at once or incrementally, however the implementation decides to do it. This also guarantees that any valid ActiveNodeSet corresponds to the current hierarchy.

NodeSet is not generally ordered in any way because implementations may be parallelized and compound statements may return nodes out of document order even in the simplest serial implementation. XSL and other processing requires XPath sets to be sorted in document order.

Interface StaticNodeSet

A StaticNodeSet is a collection of Nodes evaluated from an XPath expression. It never becomes invalid and never changes the array of node references even if the nodes are no longer are in the hierarchy or no longer match the expression that created the set. The individual nodes of a StaticNodeSet may be manipulated in the hierarchy and these changes are seen immediately by users referencing the nodes through the set.


IDL Definition
interface StaticNodeSet {
  Node               item(in unsigned long index);
  readonly attribute unsigned long    length;
};

Attributes
length of type unsigned long, readonly
The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
Methods
item
Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
Parameters
index of type unsigned long
Index into the collection.
Return Value

Node

The node at the indexth position in the NodeList, or null if that is not a valid index.

No Exceptions
Interface ActiveNodeSet

This represents a live node set obtained with the evaluation of an XPath expression.

Issue ActiveNodeSet01:
Do we need a detach() method?

IDL Definition
interface ActiveNodeSet {
  Node               nextNode()
                                        raises(DOMException);
  void               reset()
                                        raises(DOMException);
  ActiveNodeSet      cloneSet()
                                        raises(DOMException);
  ActiveNodeSet      getDocumentOrderedSet()
                                        raises(DOMException);
  StaticNodeSet      getStaticNodeSet()
                                        raises(DOMException);
};

Methods
cloneSet
Clones the ActiveNodeSet.
Issue cloneSet-1:
It was suggested that cloneSet should copy only the remaining set, which might favor incremental implementations and also make it possible to non-destructively pass on the current position. Clones must then be constructed at the appropriate position within the set and complete clones may only be constructed before processing any nodes.
Return Value

ActiveNodeSet

The new ActiveNodeSet.

Exceptions

DOMException

INVALID_STATE_ERR: The ActiveNodeSet is no longer valid.

No Parameters
getDocumentOrderedSet
This method may be called as long as the set is not invalid to get a set that is sorted into document order. Nodes which have no defined order with respect to each other (such as Attr nodes attached to an Element) will not be ordered in any particular order with respect to each other by this method.
Issue getDocumentOrdered-1:
Here are significant differences between DOM's currently proposed document order and the XPath model's document order expected by XSL and other callers of getDocumentOrderedSet. Some of the differences, we could just adopt. Others are unclear.
For example, in the fragment <foo bar1="abc"/><foo bar2="def" bar3="ghi">, DOM currently says that attribute nodes bar1 and bar2 are unordered with respect to each other, since they each have no parent. XPath and DOM both agree that bar2 and bar3 have no order with respect to each other, but XPath gives them an order with respect to their parent, giving them a definate position in the resulting sorted node set, whereas DOM does not acknowledge the ownerElement as part of the ordering relationship and makes it impossible to meaningfully sort attributes nodes of an element with elements or the attributes of other elements. I think we should adjust DOM's proposed comparison APIs and the result will help, rather than hurting, the DOM specification.
It will be much more difficult to make Attr nodes masquerading as XPath namespace nodes XPath-compatible with respect to their sort order. If it is a requirement to make this work, we have to use real Namespace nodes, IMO.
Return Value
Exceptions

DOMException

INVALID_STATE_ERR: The ActiveNodeSet is no longer valid.

No Parameters
getStaticNodeSet
This method may be called as long as the set is not invalid to force complete evaluation and return StaticNodeSet, which never becomes invalid and never changes the array of node references even if the nodes are no longer are in the hierarchy or no longer match the expression that created the set.
Return Value

StaticNodeSet

The complete evaluation of the XPath expression.

Exceptions

DOMException

INVALID_STATE_ERR: The ActiveNodeSet is no longer valid.

No Parameters
nextNode
Returns the next node from the XPath expression evaluation.
Return Value

Node

Returns the next node.

Exceptions

DOMException

INVALID_STATE_ERR: The ActiveNodeSet is no longer valid.

No Parameters
reset
Exceptions

DOMException

INVALID_STATE_ERR: The ActiveNodeSet is no longer valid.

No Parameters
No Return Value
Interface NamespaceResolver

The NamespaceResolver interface permit prefix strings in the expression to be properly bound to namespaceURI strings. The expectation is that an instance of the NamespaceResolver interface can be obtained by using binding-specific casting methods on an instance of the Element interface. This interface may also be user implemented instead of obtaining the implementation from an Element.

Issue NamespaceResolver-1:
This interface should be reconciled with the core method for namespace resolution so that it is automatically implemented by any Element
Resolution: The current proposal matches the definition in the Node interface.

IDL Definition
interface NamespaceResolver {
  DOMString          lookupNamespaceURI(in DOMString prefix);
};

Methods
lookupNamespaceURI
Look up the namespace URI associated to the given prefix, starting from this node.
Parameters
prefix of type DOMString
The prefix to look for.
Return Value

DOMString

Returns the associated namespace URI or null if none is found.

No Exceptions