What is jaxen?

The jaxen project is a Java XPath 1.0 Engine. jaxen is a universal object model walker, capable of evaluating XPath expressions across multiple models. Currently supported are dom4j, JDOM, and DOM.

What is the jaxen license?

We use the BSD 2-clause license, also known as the simplified BSD license. This is one of the least restrictive licenses. You can use jaxen to create new products without them having to be open source.

Why is jaxen useful?

After implementing an XPath engine for both dom4j and JDOM, and attempting to keep them both in sync, it was decided that factoring out the commonality would be a Good Thing. Thus, jaxen provides a single point for XPath expression evaluation, regardless of the target object model, whether its dom4j, JDOM, DOM, XOM, JavaBeans, or what not.

Why is jaxen better than [some other XPath technology]

jaxen is better than werken.xpath specifically because it better handles XPath expressions, and syntax error reporting. Additionally, since jaxen is a unified code-base, developer effort isn't split between maintaining the dom4j version and the JDOM version. More hands working on the same project reduces bug count.

jaxen may be perceived to be better than other XPath technologies since it provides a single cohesive API for evaluating XPaths against multiple object models. Learn the jaxen API, and apply it to dom4j, JDOM, XOM or DOM trees in exactly the same way.

Also, since jaxen works against an adaptor which provides InfoSet access to arbitrary object models, it should be possible to build even larger tools in terms of jaxen, to work with multiple models. For example, an XQL engine could be developed, which would automagically work with all models already supported by jaxen.

What are some related technologies?

jaxen itself is based upon SAXPath, which is an event-based model for parsing XPath expressions.

Which version of XPath does jaxen support? Does jaxen support XPath 2?

jaxen supports XPath 1.0. It does not support XPath 2.0. XPath 2.0 is a very different spec with many things to recommend it and a few things not to like as well. However XPath 2.0 is not compatible with XPath 1.0. It is far from a simple upgrade from XPath 1.0. It has a very different data model, that might well require significant revisions to jaxen's internal data structures, and possibly a very different API as well.

The current release plan focuses exclusively on XPath 1.0 compatibility. Perhaps one day someone will make a branch or fork of jaxen that supports XPath 2. However, this would be a significant undertaking, and so far little interest in this has been shown.

How do I support a different object model?

The only thing required is an implementation of the interface org.jaxen.Navigator. Not all of the interface is required, and a default implementation, in the form of org.jaxen.DefaultNavigator is also provided.

Since many of the XPath axes can be defined in terms of each other (for example, the ancestor axis is merely a the parent recursively applied), only a few low-level axis iterators are required to initially get started. Of course, you may implement them directly, instead of relying upon jaxen's composition ability.

Is jaxen only good for XPath evaluation?

No.

The DocumentNavigators provided with jaxen can be used by themselves, without the XPath evaluation engine, to provide univeral access to many object models for other technologies.

Who uses jaxen?

jaxen has been embedded directly into dom4j and XOM to provide easy XPath evaluation directly from your documents. Additionally, it's being integrated into David Megginson's NewsML Framework. Tom Copeland's PMD static code analyzer uses jaxen to query Java code structures using XPath.

How do I write a query for namespace qualified elements/attributes in Jaxen?

The XPath expression that selects elements or attributes in a namespace looks exactly the same as it does in any other XPath context; that is, use prefixed names where the prefixes are bound to the namespace URIs. For example,

/pre:bar/@xlink:href

However, because a Java program is not an XML document, it is also necessary to bind the prefixes to the appropriate namespace URIs through a NamespaceContext object. For example, this code sets up and then executes the above query:

  XPath xpath = new DOMXPath("/foo:bar/@xlink:href", nav);
  SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
  nsContext.addNamespace("pre", "http://www.foo.org/");
  nsContext.addNamespace("xlink", "http://www.w3.org/1999/xlink");
  xpath.setNamespaceContext(nsContext);
  List result = contextpath.selectNodes(document);

As a shortcut, you can simply add a namespace binding to the XPath expression's current context using the addNamespace method:

  XPath xpath = new DOMXPath("/pre:root");
  xpath.addNamespace("pre", "http://www.example.org/");
  List result = xpath.selectNodes(root);

If the namespace context does not contain a binding for a prefix that is used in the XPath expression, an UnresolvableException (a subclass of JaxenException is thrown when you attempt to evaluate it.

How do I write a query for namespace qualified elements/attributes in the default namespace?

The same way you do for elements and attributes that are in prefixed namespaces. That is, you use a prefix in the XPath expression and bind the prefix to the namespace URI. You do this even if the document you're querying uses unprefixed namespaced qualified names. In XPath 1.0, all unprefixed names are unqualified. There is no requirement that the prefixes used in the XPath expression are the same as the prefixes used in the document being queried. Only the namespace URIs need to match, not the prefixes.

For example, this code fragment queries the document [<root xmlns="http://www.example.org/"/> using the XPath expression /pre:root:

        Element root = doc.createElementNS("http://www.example.org/", "root");
        doc.appendChild(root);
        XPath xpath = new DOMXPath("/pre:root");
        SimpleNamespaceContext context = new SimpleNamespaceContext();
        context.addNamespace("pre", "http://www.example.org/");
        xpath.setNamespaceContext(context);
        List result = xpath.selectNodes(root);

Alternately, using the shortcut:

        Element root = doc.createElementNS("http://www.example.org/", "root");
        doc.appendChild(root);
        XPath xpath = new DOMXPath("/pre:root");
        xpath.addNamespace("pre", "http://www.example.org/");
        List result = xpath.selectNodes(root);