Copyright © 1999 W3C (MIT, INRIA, Keio), All Rights Reserved. W3C liability, trademark, document use and software licensing rules apply.
This specification defines the API for PAX, a full set of interfaces for evaluation of expressions that address trees that implement the Document Object Model (DOM) Level 2 interfaces or conform to the XML information set (Infoset)..
This intention of this document is to provide a proposal for an API that can at least evaluate expressions in the XML Path Language (XPath) , and return Node-sets, Booleans, Numbers, and Strings, as defined in the XPath specification, as well as other objects, such as a Range object for support of XPointers. This draft will focus on the API in Java. However, the intention is to make API definitions for at least IDL and ECMAScript, as well as Java.
This is an informal proposal for the www-dom-xpath-request@w3.org mailing list.
The XML Path Language (XPath) and the XML Pointer Language (XPointer) will be valuable tools for Web application developers. These developers need a standard and consistent method to interface to tools and objects that implement these languages.
The goal of PAX is to define an API that is:
Layered
It should be possible to layer the API so that implementors can provide only the interfaces that make sense for their users. Also, users should be able to do simple things simply, without having to be exposed to the entire API.
Complete
The API should provide the ability for users to take full advantage of language (i.e. XPath) implementations, without having to resort to proprietary interfaces.
Language Independent
The PAX API need not expose the expression language directly to the interface. Therefore, it should be possible to use PAX to address other expression languages besides XPath, such as Perl (in a limited fashion), or perhaps a full-blown XML Query Language.
This section outlines a list of potential requirements of this API.
It must be DOM-compatible, i.e., use DOM concepts rather than invent any new infrastructure (such as Nodes, lists, iterators, etc.) unless absolutely necessary.
It must be language neutral and vendor neutral. As much as we all like [insert favorite language or system here], it's important to have as much consistency as possible across "language bindings". The languages that are required are Java, ECMAScript, and IDL.
It must allow XPath expressions to define some subset of an XML document, stream, or database and provide a way of iterating over or otherwise processing that subset.
It must not require all DOM implementers to support this functionality.
It should provide an interface for XSLT Match Patterns. Though they are XSLT and not XPath, they are very useful.
It should provide a way to install XPath extension functions, but it should not define an XPath extension API (which is being done by the XSLT WG).
It should provide an interface for creating XPointers, given a context such as a DOM node.
It must provide an interface to XML Pointer Language (XPointer), meaning that it must provide an interface that returns a Range object.
It must support the setting of variables.
It must support the setting of a namespace context for the expression.
It must support an optimized expression object, which can be reused without having to re-parse the expression.
It must support thread safety for these objects to be used in multiple threads concurrently.
Key ideas in the approach are:
Define a minimal interface that can be used and implemented simply, by itself
Provide an full expression API.
Provide a context object that can track variables and extension bindings.
Provide a match pattern object.
Provide a generic type object capable of converting to language types.
Provide a namespace resolver interface.
package org.w3c.pax;
import org.w3c.dom.range.Range;
import org.w3c.dom.Node;
/**
* This represents a simple interface which any object may implement
* in order to perform an interpreted evaluate of an expression.
*/
public interface Inquirer
{
/**
* Set the namespace prefix resolver for this Inquirer.
* If the prefix resolver is not set, the Inquirer object
* will be used as the context to resolve prefixes from.
*/
void setPrefixResolver(PrefixResolver resolver);
/**
* Set the context node that will be used for this
* Inquirer object. If the context node is not
* set, the Inquirer object will be used as the context
* node.
*/
void setContextNode(Node context);
/**
* Select a list of nodes from current context.
*/
NodeIterator selectNodes(String queryString);
/**
* Select a single node from the current context.
*/
Node selectSingleNode(String queryString);
/**
* Select a range of text from the current context. Any
* object will be converted to text, as per the conversion
* rules for a String cast for the given language.
*/
String getText(String queryString);
/**
* Select a Range from the current context,
* giving an XPointer string, which may be a full
* URL, with XPointer fragment identifier.
*/
Range getRange(String xpointerString);
}
package org.w3c.pax;
/**
* This object resolves prefixes into namespaces.
*/
public interface PrefixResolver
{
/**
* Given a prefix, return a URI.
*/
String getURI(String prefix);
}
package org.w3c.pax;
import java.text.ParseException;
/**
* This class can parse expression strings and produce Expression objects.
*/
public abstract class ExpressionFactory
{
/**
* Factory method to create an instance of an ExpressionFactory. The
* class which is instanciated is found via the org.w3c.pax.Expression.LANG
* property, for instance org.w3c.pax.Expression.XPath.
* @language The expression language that will be parsed, for
* instance, "XPath".
* @return A new instance of an ExpressionFactory object.
* @exception IllegalAccessException Thrown if the registered class
* is not public or in another package.
* @exception InstantiationException Thrown if the registered class
* cannot be instantiated because it is an interface or is an abstract class.
* @exception InstantiationException Thrown if the registered class
* cannot be found.
*/
public static ExpressionFactory newInstance(String language)
throws java.lang.IllegalAccessException,
java.lang.InstantiationException,
java.lang.ClassNotFoundException
{
String factoryName = System.getProperty("org.w3c.pax.Expression."+type);
Class factoryClass = Class.forName(factoryName);
return (Processor)factoryClass.newInstance();
}
/**
* Given a string, create an Expression object.
* @param prefixResolver An object that is able to resolve prefixes in
* the Expression to namespaces.
* @return A valid Expression object.
* @exception ParseException thrown if the expression is not valid.
*/
public abstract Expression create(PrefixResolver prefixResolver)
throws ParseException;
}
package org.w3c.pax;
/**
* This class represents an expression, which can be evaluated in the
* context of a node and an XEnvironment object.
*/
public interface Expression
{
/**
* Evaluate this expression in the context of a node and an
* XEnvironment object.
* @param context The context node from where a search will start.
* @param environment The environment from where variables and the
* like will be resolved. (Note that passing this object, rather
* than having a setEnvironment call on Expression, makes this
* object threadsafe.)
* @return The result of the expression, or null if it failed.
*/
XObject evaluate(Node context, XEnvironment environment);
/**
* Evaluate this expression as a match pattern.
* @param context The node which will be tested to see if it matches
* this expression.
* @param environment The environment from where variables and the
* like will be resolved. (Note that passing this object, rather
* than having a setEnvironment call on Expression, makes this
* object threadsafe.)
* @return A value which is one of MATCH_SCORE_NONE, MATCH_SCORE_QNAME,
* MATCH_SCORE_NSWILD, MATCH_SCORE_NODETEST, or MATCH_SCORE_OTHER.
*/
int match(Node context, XEnvironment environment)
throws BadMatchPatternException;
/**
* The match score if no match is made.
*/
public static final double MATCH_SCORE_NONE = Double.NEGATIVE_INFINITY;
/**
* The match score if the pattern has the form
* of a QName optionally preceded by an @ character.
*/
public static final double MATCH_SCORE_QNAME = 0.0;
/**
* The match score if the pattern pattern has the form NCName:*.
*/
public static final double MATCH_SCORE_NSWILD = -0.25;
/**
* The match score if the pattern consists of just a NodeTest.
*/
public static final double MATCH_SCORE_NODETEST = -0.5;
/**
* The match score if the pattern consists of something
* other than just a NodeTest or just a qname.
*/
public static final double MATCH_SCORE_OTHER = 0.5;
}
package org.w3c.pax;
/**
* This class represents the environment for an Expression
* object's evaluation.
*/
public interface XEnvironment
{
/**
* Set the namespace prefix resolver for this XEnvironment.
* The PrefixResolver must be set if namespace prefixes are
* used for variable or extension names.
* @param An object that fullfills the PrefixResolver interface.
*/
void setPrefixResolver(PrefixResolver resolver);
/**
* Push a string variable onto the variable stack.
* @param name A QName which may be prefixed.
* @param value A String value.
*/
void pushVariable(String name, String value);
/**
* Push an XObject variable onto the variable stack.
* @param name A QName which may be prefixed.
* @param value A String value.
*/
void pushVariable(String name, XObject value);
/**
* Pop the last variable pushed from the stack.
*/
void popVariable();
// TO BE DONE: I need stuff for extensions binding here.
}
package org.w3c.pax;
/**
* This class represents the return value from an expression,
* and is capable of converting the object to various types,
* such as a string or number.
*/
public interface XObject
{
public static final short NODESET = 1;
public static final short BOOLEAN = 2;
public static final short STRING = 3;
public static final short NUMBER = 4;
/**
* Get an integer representing the type of the object.
*/
public short getType();
/**
* Cast result object to a number.
*/
public double num();
/**
* Cast result object to a boolean.
*/
public boolean bool();
/**
* Cast result object to a string.
*/
public String str();
/**
* Return a java object that's the raw form of the XObject.
*/
public Object object();
/**
* Get the result object as a nodelist.
*/
public NodeIterator nodeset();
/**
* Tell if one object is less than the other.
*/
public boolean lessThan(XObject obj2);
/**
* Tell if one object is less than or equal to the other.
*/
public boolean lessThanOrEqual(XObject obj2);
/**
* Tell if one object is less than the other.
*/
public boolean greaterThan(XObject obj2);
/**
* Tell if one object is less than the other.
*/
public boolean greaterThanOrEqual(XObject obj2);
/**
* Tell if two objects are functionally equal.
*/
public boolean equals(XObject obj2);
/**
* Tell if two objects are functionally not equal.
*/
public boolean notEquals(XObject obj2);
}
package org.w3c.pax;
/**
* An object of this class may be thrown if an
* expression is used that is not a valid match
* expression.
*/
public class BadMatchPatternException extends Exception
{
BadMatchPatternException(String msg)
{
super(msg);
}
}
To Be Done
To Be Done