Table of Contents
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.
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.
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.
Copyright 2001, 2002 Elliotte Rusty Harold | elharo@metalab.unc.edu | Last Modified September 12, 2002 |
Up To Cafe con Leche |