Tree-based APIs like DOM are very useful when programmers want
to keep the entire document in memory at once with
random access to the entire tree. Unfortunately DOM suffers
from a number of design flaws and limitations that make it
less than ideal as a Java API for processing XML. These include:

DOM had to be backwards compatible with the hackish,
poorly thought out, unplanned object models used in third
generation web browsers.

DOM was designed by a committee trying to reconcile
differences
between the object models implemented by
Netscape, Microsoft, and other vendors. They needed
a solution that was at least minimally acceptable
to everybody, which resulted in an API that’s maximally
acceptable to no one.

DOM is a cross-language API
defined in IDL, and thus
limited to those features and classes that are available
in essentially all programming languages, including
not fully-object oriented scripting languages like
JavaScript and Visual Basic. It is a lowest common denominator API.
It does not take full advantage of Java, nor does it
adhere to Java best practices, naming conventions, and
coding standards.

DOM must work for both HTML (not just XHTML, but traditional malformed HTML)
and XML.

Together these constraints made DOM a lot more clumsy and hard-to-use than it
should have been. I’m virtually certain that if you’ve read
the last five chapters, you’ve often found yourself muttering
in rather colorful language
about some of the more brain damaged aspects of DOM.
I know I certainly did as I wrote those chapters. In almost
every case, the specific problem that elicits such complaints
is a result of one of the above four constraints on the
design of DOM.

JDOM is a tree-based API for processing XML documents with
Java that threw out DOM’s limitations and assumptions and
started from scratch.
It is designed purely for XML, purely for Java, and with no
concern for backwards compatibility with earlier, similar
APIs. It is thus much cleaner and much simpler than DOM. Most
developers find JDOM to be far more intuitive and easy to use
than DOM. It’s not that JDOM will enable you to
do anything you can’t do with DOM.
However, writing the same program with JDOM
will normally take you less time and have fewer bugs when
finished, simply because of the greater intuitiveness of the API.
In many ways, JDOM is to DOM as Java is to C++, a much
improved, incompatible replacement for the earlier more
complex technology.

Caution

JDOM is still in beta at the time of this writing.
This chapter is based on the most current CVS version
available, which is shortly after beta-8 and somewhere
before beta-9. The API has been stabilizing and I don’t
foresee any major changes between now and 1.0.
However, a number of the details are likely to shift.
I’d definitely check the method signatures with the
latest version of the JavaDoc API documentation.

What is JDOM?

JDOM is an open source, tree-based, pure Java
API for parsing, creating, manipulating, and serializing XML
documents. JDOM was invented by Brett McLaughlin and Jason
Hunter
in the Spring of 2000. I asked Jason how it happened, and
here’s what he told me:

In the early months of 2000, in a time before I knew Brett, I found
myself working with XML for a contract project and growing increasingly
frustrated with DOM as a way to solve my problems. My mind had an
expectation for what a Java-based XML manipulation API would look like.
DOM wasn’t anything like it.

In the spring of 2000, I attended Brett’s talk on DOM and SAX at the
O’Reilly Conference on Enterprise Java. I was hoping he’d share with me
the DOM philosophy so I could see why reality wasn’t matching my
expectations. Rather than clearing things up, I found every fifth slide
in his presentation was titled "Gotcha!" and listed one more thing you
had to watch out for.

After his talk we sat down together on the lawn in San Jose. It was a
gorgeous spring day. He was just about to release a book that was
clearly destined to be a bestseller (Java and XML buzzwords in the
title, what can go wrong, right elharo?). I was telling him some of
what that means for a person’s career, based on my experience with a
popular servlets book. I used the opportunity to ask him (someone far
more expert in XML than myself at the time), "Why does it have to be
like this?" He thought about it, we talked about it, and ten minutes
later we decided to start an open source project to create a
Java-specific XML object model. It was the first alternative to DOM in
the Java world.

We worked for about a month designing the early API. We each had our
role to play. Brett made sure the API was consistent with XML
specifications. I made sure the API was acceptable to a Java programmer
who wanted to just use XML and get on with their life. We had two
private betas, then a public beta 3. James Duncan Davidson was helpful
during the two private betas, especially on the interfaces vs classes
debate.

Since then numerous people have contributed to JDOM’s development
including Alex Rosen, Alex Chafee, James Duncan Davidson,
Philip Nelson, Jools Enticknap, Bradley
S. Huffman, and yours truly.

JDOM is open source like SAX and DOM. (Proprietary XML APIs
really have not caught on.) Hunter and McLaughlin publish it
under the very
liberal Apache license. Essentially you can do anything you
want with it except use the name “JDOM” for derivative
works. It has already been forked once resulting in James
Strachan’s dom4j.

dom4j

James Strachan forked JDOM in late 2000 to experiment with
using interfaces built by factory methods to represent the nodes
instead of concrete classes built by constructors. The result was
dom4j.

dom4j has some features I like, including integrated XPath support
and a generic
Node interface that makes
document
navigation a lot simpler.
However, in my experience most programmers find it much
easier to work with class-based APIs like JDOM than with pure
interface-based APIs like dom4j and DOM. Furthermore,
classes can enforce constraints such as “the name property of an
Element must be a legal XML name”.
Interfaces can’t do that. In my opinion, dom4j makes it too
easy to slip out of
the constraints of XML and produce a
malformed document.

Like DOM, JDOM represents an XML document as a tree composed
of elements, attributes, comments, processing instructions,
text nodes, CDATA sections, and so forth.
The entire tree is available at any time. Unlike SAX,
JDOM can access any part of the tree at any time.
Unlike DOM, all the different kinds of nodes in the tree are
represented by concrete classes rather than interfaces.
Furthermore, there is no generic
Node interface or class which
all the different node classes implement or extend.
(This is personally my least favorite aspect of the JDOM
design. It makes tree-walking and search operations
far more cumbersome than they are in DOM.)

JDOM is written in and for Java. It consistently uses the Java coding
conventions and the class library. For example,
all primary JDOM classes have
equals(),
toString(), and
hashCode() methods.
They all implement the
Cloneable
and Serializable interfaces.
The children of an Element or
a Document object are stored in a
java.util.List. JDOM strives to be
correct not just with respect to XML but also with respect to
Java.

JDOM does not itself include a parser. Instead it depends
on a SAX parser with a custom ContentHandler
to parse documents and build JDOM models from them.
Xerces 1.4.4 is bundled with JDOM. However, it can work
equally well with any
SAX2 compliant parser including
Crimson, Ælfred, the Oracle XML Parser for Java, Piccolo,
Xerces-2,
and more. Any of these can read an XML document
and feed it into JDOM. JDOM can also convert DOM
Document objects into
JDOM Document objects, which is useful
for piping the output of existing DOM programs to the input of
a JDOM program. However, if you’re working with a stream of
XML data read from a disk or a network, it’s preferable to use
SAX to produce the JDOM tree because it avoids the
overhead of building the in-memory tree twice in two different
representations.

Like DOM (and unlike SAX) JDOM can build a new XML tree in
memory. Data for the tree can come from a non-XML source like a database,
from literals in the Java program, or
from calculations as in many of the Fibonacci number examples
in this book. When creating new XML documents from scratch
(rather than reading them from a parser), JDOM checks all the
data for well-formedness. For example, unlike many
DOM implementations, JDOM does not allow programs to create
comments whose data includes the double hyphen
-- or elements and attributes
whose namespace mapping conflict in impossible ways.

Once a document has been loaded into memory, whether by
creating it from scratch or by parsing it from a stream,
JDOM can modify the document. A JDOM tree is fully
read-write. All parts of the tree can be moved, deleted, and
added to, subject to the usual restrictions of XML.
(For instance, you can add an attribute to an element but not
to a comment.) Unlike DOM, there are no annoying read-only
sections of the tree that you can’t change.

Finally, when you’re finished working with a document in
memory, JDOM lets you serialize it back out to disk or onto a
stream as a sequence of bytes. JDOM provides numerous options
to specify the encoding, indenting, line end characters, and
other details of serialization.
Alternately, if you don’t want to convert the document to a
stream, you can produce a SAX event sequence or a DOM document
as output instead.