-
Notifications
You must be signed in to change notification settings - Fork 118
JDOM2 Features
Apart from the details described below, it is important not to forget that JDOM2 has arrived with a completely different package name: - all JDOM2 classes are in the org.jdom2.*
package hierarchy.
This change is guaranteed to break all compatibility with JDOM1. The decision was made to do it this way so that changes to the API are possible, and it will require that JDOM users will need to re-visit their code to change the import statements (at least), and that it is possible to simultaneously run both JDOM and JDOM2 in the same Java VM if necessary.
In addition to this obvious change, there are a lot of other changes.
'Generics' has been applied to all levels of JDOM, in too many places to list them all, but of significance are:
- Element (and where applicable, Document) Content, Namespace and Attribute collection manipulation
- XPath expressions
- XSL Transform interfaces
Some of the major changes are described in more depth.
All Collection-based values now have the correct generic typing, and, where it is not possible to guarantee a generic type through the JDOM API, the Filter class can be used to 'coerce' the data in to the correct type. In other words, the Filter class not only applies a Generic typing to the data, but it (silently) filters out any content that does not conform to the Filter's specification.
This makes the following structures possible:
List<CDATA> childcdata = rootelement.getContent(Filters.cdata());
Or, put a different way, it also makes nicely typed loops possible:
for (CDATA cdata : rootelement.getContent(Filters.cdata()) {
...
}
JDOM has always allowed the 'chaining' of JDOM method calls (where possible). For example:
Element root = new Element("root").setAttribute("att","val").addContent(new Text("string"));
This functionality has been expanded where possible to other areas, using a common underlying API, but returning appropriate data types.
For example, JDOM has always had the public Content detach();
method on the Content types. Now in JDOM2 the actual Content's type is returned (which allows chaining of methods, and reduces the requirement for casting values):
Element p = new Element("parent");
Element c = new Element("child");
p.addContent(c);
c.detach().setAttribute("att", "val");
Methods impacted by this type of change are:
- detach()
- setParent()
- clone()
- CDATA.setText() now returns CDATA (not Text).
The following major features have been added or updated
Namespaces create a fair amount of confusion, and a number of different mechanisms existed in the code to locate and process Namespace data. These numerous internal mechanisms were not available to JDOM users, resulting in the users having to implement similar functionality in their code. These disparate mechanisms can now be replaced by just two 'standard' mechanisms:
- Content class now has three new methods
List<Namespace> getNamespacesInScope()
,List<Namespace> getNamespacesInherited()
, andList<Namespace> getNamespacesIntroduced()
. These detail those Namespaces which are in scope for the Content, which of the in-scope Namespaces are inherited from the Parent scope, and which are introduced by the content. These three methods are 'dynamic', calculating the values as the method is called. This means that it can be slow to call this method often. - New class NamespaceStack (which is a java.util.Iterable instance) has been introduced which allows for the JDOM content to be processed in a batch. This is more efficient than the getNamespacesInScope() method calls, but it needs to be maintained as the document is traversed. There are two methods used for maintaining the namespaceStack - push(Element) and pop(). The actual namespaces in scope can then be queried using the iterator() method, as well as the addedForward() and addedReverse() methods.
In addition to centralizing the Namespace handling of JDOM content, JDOM now has a reliable and consistent mechanism for ordering Namespace values. Namespaces are always accessed from the perspective of some Content, for example, an Element. In this case (Element), the order of the Namespaces in scope will be: first the Element's Namespace, followed by the remaining Namespaces in alphabetical order by prefix.
All JDOM processes that expose Namespaces will use the above system, thus, all iterators, lists, and XML output will output the XMLNamespaces in that order.
When outputting JDOM in some other format, the Namespace declarations will always be output before any Attributes for the Element.
It is worth noting that in JDOM 1.x that Namespaces are not centrally coordinated, so to identify the Namespaces in scope on an Element you would have to inspect 5 places:
- the Element's Namespace
- each of the Element's Attributes
- Any additional namespaces declared explicitly for the Element
- any Namespace set on the Element's parent, but not redeclared by something on this Element
- any of the default namespaces ( the default and xml namspaces).
The getNamespacesInScope() method does exactly the above, so it requires a scan of the Element and it's ancestry. Do not use it in 'tight' loops or performance critical code. Use the NamespaceStack implementation instead.
The getNamespacesIntroduced() method returns a subset of the getNamespacesInScope() method. The subset contains only those namespaces which are on this content, but are not on the content's parent. The order of the Namespaces is the same as they would appear in the getNamespacesInScope().
The getNamespacesInherited() method returns a subset of the getNamespacesInScope() method too. This subset contains only those Namespaces in scope on this Element, but also in scope on the Element's parent. The order of the Namespaces is the same as they would appear in the getNamespacesInScope().
The getNamespacesInherited() and getNamespacesIntroduced() are mutually exclusive, and the union of them will always be the full getNamespacesInScope() set.
Special notes about this functionality are:
- Not all JDOM content has an Element parent, either becuase it is a document-level Content, or because it is detached. These instances are assumed to have a 'virtual' ancestry for Namespace purposes, and this virtual ancestor has the in-scope set of Namespaces consisting of the XML namespace xmlns:xml="http://www.w3.org/XML/1998/namespace" and the NO_NAMESPACE Namspace (URI is "", and prefix is "").
- For all non-Element and non-Attribute content (Comment, Text, CDATA, Processing, EntityRef, DocType) the in-scope Namespaces will be the same as the content's Parent Element (or the 'virtual' set if the content does not have a parent Element). The getNamespacesIntroduced() list will always be empty. The order for these content types will be the same as the order in the parent Element even though these content types do not have a Namespace concept.
- Attributes have always been a special case for Namespaces. Non-prefixed Attributes are always in the NO_NAMESPACE namespace (even if the Attribute's parent Element has re-bound the 'default' (no-prefix) namespace to some other URI). Thus, it is possible for the Namespace set for an Attribute to be different from the Attribute's parent Element (because the Attribute can potentially re-bind the "" prefix to the "" URI). It also follows that the order of the in-scope Namespaces will always be the Attribute's Namespace, followed by other in-scope Namespaces in prefix order. The getNamspacesIntroduced() set will always be empty unless the Attribute re-binds the "" prefix to the "" URI.
The XPath library has been substantially revamped behind-the-scenes. The API is currently unchanged, though it will be changing in the near future to make the factory-type methods work correctly.
The new implementation of XPath still uses (by default) Jaxen in the back-end, but it no longer uses the 'interface layer' embedded in the Jaxen library, but implements a replacement interface layer in JDOM. The new interface layer allows for the build process to be simpler (removes the circular compile dependency). Additionally, the current JDOM layer in JAXEN only supports org.jdom.*
classes, not org.jdom2.*
.
The StAX library has been available since almost 2003, and in 2006 it was formally introduced in to the Java6 release. The library is independently available for Java5 though.
JDOM2 introduces input and output handlers for the StAX API, allowing JDOM documents to be built from StAX XMLStreamReader and XMLEventReader instances, and allowing JDOM to be directly output to StAX XMLStreamWriter and XMLEventWriter instances.
In the 'spirit' of StAX, JDOM allows for the streams to be processed in 'fragmets', in such a way that you can parse JDOM fragments from the StAX readers whatever their source, and JDOM can be written in fragments to StAX writers.
In addition to the major extensions and features above, the following notable changes have been made too:
- There were a number of places in JDOM where reflection and introspection was used to determine what features were available. This sort of logic was required to support Java 1.2 while still also making certain Java 1.4 functionality possible. These places have been stripped and replaced with cleaner direct access to code functionality, which now effectively precludes support for previous versions of Java, but that's what JDOM2 is all about.
- All JDOM class instances that have core Java API interfaces (List, Iterator, ListIterator, etc.) now behave in the exact same way as those core API implementations. JDOM classes throw NullPointerException, ConcurrentModificationsException, ClassCastException, NoSuchElementException, IllegalStateException, etc. in the same circumstances that the core API implementations would. This provides a measure of consistency and predictability.
- The core JDOM Lists and Iterators have been streamlined and profiled to make them more efficient. Navigating JDOM is more efficient.
Filter instances keep their match() method, but are extended to have the filter() method which returns the input value in the same generic type as the Filter.
[JDOM Home](http://www.jdom.org)
Stable Release
- [Download](http://www.jdom.org/downloads/index.html)
- [JavaDoc](http://www.jdom.org/docs/apidocs/index.html)
JDOM 2.x
- Overview
- Getting Started
- JDOM on Android
- [JavaDoc](http://hunterhacker.github.com/jdom/jdom2/apidocs/index.html)
- [Coverage](http://hunterhacker.github.com/jdom/jdom2/coverage/index.html)
- [UnitTests](http://hunterhacker.github.com/jdom/jdom2/junit.report/index.html)
- Features
- JDOM 1.x to JDOM 2.x
- Dependencies
Developing JDOM