[jdom-interest] DOM and JDOM: criticisms

Amy Lewis amyzing at talsever.com
Wed Dec 6 15:52:59 PST 2000


DOM and JDOM: some criticisms

Let's start this with some theory.  This won't be theory in the
Computer Science sense; it's a more casual discussion of how to think
about things.  In this case, it's a discussion of how to think about
trees, and about trees conforming to XML specs in particular.

There are a number of ways of thinking about trees (as directed graphs
composed of arcs and edges and things), but the commonest is probably
to think of a tree as a collection of nodes.  Both DOM and JDOM at
least on the surface use this model.  So what is it that makes a
collection of objects into a tree of nodes?  What's a node?

For it to be useful, the concept of a node ought to participate in the
tree.  That is, it ought to contribute to the structure (trees are
*about* structure, so whatever it is that makes that structure is the
fundamental concept).  Nodes particpate in a tree by having a
connection to at least one other node in the tree.  The major types of
connection are to-parent and to-child.

If you accept this, then there are three classes of nodes in a tree:
nodes that, conceptually, can have children, but no parent (the root
node); nodes that, conceptually, can have a parent as well as children
(branch nodes); and nodes that, conceptually, may not have children
(but have a parent).  This leaves out "nodes" that have no parent and
no children, since by the definition of participation, they don't--so
they aren't nodes.

In the classic filesystem example, there is normally one root,
directories (or folders) are branches, and files are leaves.  This
isn't actually true, though--files don't know their parents, so they
don't participate.  The only real nodes in the tree are the
directories (and root), which can have files as content.

Applying this to the content of XML specs, and you get approximately
the following map:
document: root
element: branch
processing instruction: leaf
comment: leaf
attribute: leaf
text: leaf

Other node types also exist, and are generally also leaf nodes.

(tangentially, both the specs and common practice support a view of
text (not all text, but most text in text-only elements) as content
rather than as independent nodes--the mixed element model makes this a
rather difficult problem)

The map above, though, is not how either DOM or JDOM models XML.

In DOM, all nodes are branch nodes.  Even the root node is a branch
node, but more distressingly, all the leaf nodes are branch nodes. 
This is weird.  An attribute node can't have children; how can it
be-a branch node?  The reason for this is because the DOM definition of
node is broad: anything that some node type can do, all have the
signature for.  It's pretty silly.

Apart from that, due to the specification that every node must be aware
of its document, even when it isn't a member of the tree of that
document, means that every node has a direct connection to the
document.  Super weird, and a major pain.

If you define all nodes that can have parents to expose getParent(),
you can getDocument() with: if (getParent() != null) return
getParent().getDocument(); return null;.  Document has return this;. 
Storing both parentage and "documentage" is redundant; it's
overspecified.

JDOM goes to the other extreme.  There are only two node types in DOM:
Document (which is a root node) and Element (which is a branch node). 
All other classes in the package are the content of those two nodes. 
They don't particpate in the tree structure, so it's up to the
programmer to keep track of where they belong.  This is also weird.

A part of the reason that JDOM seems willing to orphan all its child
nodes has to do with the use of String as the "node type" for text. 
java.lang.String isn't a node (at least, not by the definition of
participation).  If your API is willing to treat it as such, by putting
the burden on the programmer, then there's no reason not to treat other
nodes equally (or equally poorly, perhpas).  Brett (I think it was
Brett) stated that returning the text content of elements as Strings
was a "hard requirement".  I'm not sure what this means.  If it means
that they *must* *be* *stored* as Strings, then I think it's
overspecified (storage shouldn't ever be specified).  It should be
equally effective to allow a singleton text string to be promoted and
returned as content (not my child, just a part of me ...).  This begs
the question of how to cope with mixed content, but the temptation to
allow a MixedContentException does come powerfully to mind.  It might
also be worth checking out javax.swing.text.Segment for a mutable
string object (XML is rather document oriented, so both java.text and
javax.swing.text should, perhaps, be mined at least for ideas).

Okay, having made the criticism, it's only fair to allow someone else
to take potshots at me, I suppose.

For JDOM, I'd suggest that an interface like the following would
promote certain styles of programming (particularly path- and
iterator-based styles):

public interface Node
{
    String getName(); // comments & text don't have names; everyone else does
    Node getParent(); // Document has no parent; everyone else does
    String getText(); // pretty much everybody has content
    Document getDocument(); // it's free, recursively
    DocumentIterator iterator(); // see below
}

This permits an "iterator" (not implementing java.util.Iterator) with
the following interface:

public interface DocumentIterator // no reason not to be concrete class
{
    boolean hasNext(); // document order
    boolean hasPrevious(); // document order
    boolean hasParent();
    boolean hasChild();
    boolean hasNextSibling();
    boolean hasPreviousSibling();

    next();
    previous();
    parent(); // a bit redundant
    child();  // or firstChild(), perhaps
    nextSibling();
    previousSibling();
}

Element would expose various ways to getChild(), including the one
after this one here, and the one before this one here (and the first
one and last one).  The interface here wouldn't need to be core to JDOM
... but having all the JDOM node types implement the interface given
above (with the exception of iterator(), perhaps), would *allow* this
sort of programming, which in the current state of JDOM is basically
infeasible.  When the members of the tree won't keep track of
themselves, having to keep track of them outside the tree rapidly turns
into snarls of special cases.

The interface also enables a particular style of own-path-language
programming, but I don't want to go there right now, I think.

Hmmm, running toward 150 lines; better stop ....

I have an extremely incomplete API that implements some of these ideas
(incompletely), if there's someone who wants to see some code (but it's
not complete, okay?).  *laugh*

I hope that no one takes offense--or at least not too much--from this. 
I'd really prefer to use JDOM, if only it were extensible enough to
handle the situations that I regularly encounter.

Amy!
-- 
Amelia A. Lewis          alicorn at mindspring.com          amyzing at talsever.com
How do you make a cat go moo?  Ask it: "Does a dog have the Buddha-nature?"



More information about the jdom-interest mailing list