Chapter 14. JDOM

Table of Contents

What is JDOM?
Creating XML Elements with JDOM
Creating XML Documents with JDOM
Writing XML Documents with JDOM
Document Type Declarations
Namespaces
Reading XML Documents with JDOM
Navigating JDOM Trees
Talking to DOM Programs
Talking to SAX Programs
Configuring SAXBuilder
SAXOutputter
Java Integration
Serializing JDOM Objects
Synchronizing JDOM Objects
Testing Equality
Hash codes
String representations
Cloning
What JDOM doesn’t do
Summary

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:

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.

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.


Copyright 2001, 2002 Elliotte Rusty Haroldelharo@metalab.unc.eduLast Modified September 12, 2002
Up To Cafe con Leche