Introduction to DOM

Posted by

Introduction

What is a DOM XML parser?

What is DOM?

Overview

API Package Names

Important interfaces in the API

Introduction


This tutorial is a simple introduction to DOM. You can learn more about DOM in this Java and XML book.

As a Java programmer, once you have some XML documents, you will probably need to access the information contained in them using your Java code. Since the XML document is just a text file, you can write your own text file reader which interprets the information in the XML document in a way that your code can use. It is a very time consuming process to write such an XML document reader, and if you think about it, such code would have to be written over and over again for different programs that needed access to the information in XML documents. The W3C realized that this is the case and they created a standard way to create these “XML document readers” or XML parsers. The good news is that you don’t have to write these parsers, free parsers are provided by many companies out there, including Sun, Datachannel and IBM. These parsers are written in Java too, you must use XML parsers written in Java in your Java programs.

What is a DOM XML parser?


A DOM XML parser is a Java program that converts your XML documents into some Java object model. Once you have parsed an XML document, it exists in the memory of you Java Virutal Machine as a bunch of objects. When you need to access or modify information stored in the XML document, you dont have to manipulate the XML document file directly, instead you must access and modify the information through these objects in memory. So the DOM XML parser creates a Java document object representaion of your XML document file. You can learn more about JDOM in this Java and XML book.

The parser also performs some simple text processing as it creates an object model of your XML document; it expands all entities used in the file and it compares the structure of the information in the XML document to a DTD (if one is used). Once the simple processing is successful, the parser creates a document object representation of your XML document file. In order to access and modify the information in this document object, you need a reference object (of some class type) in order to call methods on the document object. The W3C has also created a set of Java interfaces called the Document Object Model API, which allow you to access and modify information in a document object created by the XML parser. So instead of accessing this document object with a reference of its implementation class type, the W3C expects you to access the document object with the standard DOM Java interfaces. The document class must implement these DOM interfaces.

DOM is just a set of Java interfaces which have been defined by the W3C, however, no implementations of these interfaces are provided. The XML parser writers must provide the implementations for the DOM interfaces themselves.

Since XML parsers may be written for any platform and language, the W3C has not provided an implementation for the DOM interfaces, and it leaves it up to the XML parser impementor to provide a good implementation. By doing this, another advantage is that your XML documents and Java programs (that you write) are not dependent on any particular parser.

What is DOM?


In order for your Java programs to access the information in XML documents, the parser must read the XML files from the first layer. The parser processes the file by checking the information contained in it for validity (by using a DTD if one is used) and expanding all the entities used in the file. Then this (processed) XML document is converted into an XML document object in memory by the XML parser. This document object contains a tree of nodes that contain the data and structure of the information contained in the XML document. This tree of nodes can be accessed and modified using the DOM API.

DOM is similar to the Swing component models, like TableModel, ListModel and TreeModel. These models are simply interfaces which must be implemented by classes that contain the actual data. For example, if you wish to display information in a 2D array to a JTable, you must create a class that contains the 2D array and then have this class implement the TableModel interface. So the TableModel does not contain the data, it merely allows the JTable to access the underlying 2D data; the data exists in an instance (object) of the class that implements the model. The DOM does not contain the data, but merely allows you to access your underlying XML data from the Java programs that you write. The document object contains the data, the class (of which this document object is an instance of) also implements the appropriate DOM interfaces. The parser has the responsibility of providing the implementation classes for the interfaces and also a way to instantiate them.

So the parser creates some objects, which are instances of some classes that implement certain interfaces defined in the DOM API. These objects are instantiated when the Parser reads an XML document. Now, instead of accessing these objects directly, you rely on using some Java interfaces (defined in the DOM API by the W3C) to access and manipulate these objects. These objects effectively contain the information that is in your XML document, but they only allow you to access and modify this information using the Java interfaces defined in the DOM API. So the Document Object Model is very similar to the Swing models (like TreeModel, ListModel and TableModel) which is just a set of interfaces without the implementation. This entire process is illustrated in Figure 1.

The good news about DOM and XML Parsers is that you don’t have to implement the DOM API or write the parser. There are many companies that provide XML Parsers for different languages and they all implement the DOM interfaces.

Overview


The DOM API allows hierarchical access to the information in an XML document. An XML Parser converts the information in an XML document into a tree of nodes after parsing the document. DOM allows you to access this tree of nodes using the Java interfaces defined in the DOM API. The entire XML document, no matter how simple or how complicated, is converted into a tree of nodes, and all the nodes start from one root node, which is called a document object, hence the name Document Object Model. Once a document object tree has been created (by the XML parser, or your own code), you can access elements in that tree and you can also modify, delete and create leaves and branches by using the interfaces in the API. Figure 2 shows how information in an XML document can be represented as a tree of nodes.

In the document object tree, everything is a node. A node may have other nodes inside it and the node itself can hold information, like its tag-name and value and its child nodes (if any). This hierarchical organization of information is similar to a file system, where files and folders are organized hierarchically, a folder may have files in it or other folders, and everything is descended from one root folder. Similarly, a document object is descended from one node, and it may have other nodes inside it. The document object itself is a node.

The DOM API defines a minimal set of (language and platform independent) interfaces for accessing and manipulating the content and structure of information stored in XML documents, in a hierarchical manner.

API Package Names


The interfaces for DOM are required (by the W3C) to exist in the org.w3c.dom package. You have to use the following include statement in your programs that use DOM: import org.w3c.dom.*; . The implementation for the Java interfaces in these packages are provided by the XML parser that you choose to use. The DOM interfaces are also shipped with the XML parser implementation that you use, and you have to put the implementation class files (or jar file) in your CLASSPATH.

However, the code to instantiate DOM objects is dependent on the parser that you are using. Remember, DOM is just a set of interfaces, and interfaces can’t be instantiated in Java; only the classes that implement these interfaces may be instantiated. With the parsers used in this book, it only takes one line of XML parser specific code to instantiate a DOM object (using some specific XML parser). Once the XML parser specific object has been instantiated (that implements the appropriate DOM interfaces), you should access these objects only through the DOM interfaces. So, except for the one line of XML parser specific code, all your other code can be completely standards based and portable. If you use the factory pattern to instantiate the objects that implement DOM interfaces, then your classes will be completely portable and won’t even have that one line of parser specific code embedded in them.

Important interfaces in the API


An XML document object that is created by the parser (after reading a XML file (contains a tree of Node objects (i.e. instances of some Node interface implementation class). In DOM, everything is a Node. The other interfaces are provided to make things more object oriented, but you can manipulate all your information in DOM by just using the Node interface. Figure 3 shows the inheritance relationships between some of the important interfaces.

The root Node object of the document tree is also a Document object; Document is a subclass of Node. Every DOM object must have a root. Another important interface is the Element interface (which is a subclass of Node); the Element interface can be used to access the elements in a DOM Document object tree.

The Node interface encapsulates access to a lot of information about a node, some of this information is listed in Table 1.

The Node interface allows you to find out the following information about a Node object

Examples

What is the Node’s type, tag name and value?

<email> xml@beanfactory.com </email>

For this email Node (and Element), the Node type is Node.ELEMENT_NODE. The tag name is email. The Node’s value is “xml@beanfactory.com”.

What are the Node’s children Nodes (if it has any)?

<person>

<name> Nazmul Idris </name>

<email> xml@beanfactory.com </email>

</person>

The person Node has two children Nodes, name and email.

Does the Node have any children?

<addressbook>

<person> … </person>

<person> … </person>

</addressbook>

The addressbook Node has children.

<email> xml@beanfactory.com </email>

The email Node does not have any children.

Figure 4 illustrates a sample XML Document object tree and describes all the Node objects that are contained in it.

You can find out if a Node has children or not by using the hasChildNodes() method. Node is a simple interface and you have to make sure that you follow the rules in Table 2 when using it.

Rule

Example

If a Node object has a value (i.e. it contains some text data) then it may or may not have children elements.

<name> Nazmul Idris </name>

The name Node (and Element) does not have children elements, only data.

If a Node object has children then it may or may not have a value

<person>

some data

<name> Nazmul Idris </name>

<email> xml@beanfactory.com </email>

</person>

The person Node (and Element) may have a value as well as other child Nodes (Elements)

A Node may also have no children or no value.

<indexmarker/>

The indexmarker Node does not have any children and neither does it contain any data.

If a Node has children, then it may or may not have a value. In Figure 4, the person element has children Nodes and a value. The email and name Nodes don’t have any children and have values. If a Node has no children, it might also contain no value (like an element with an EMPTY data storage declaration).

The getNodeType() method returns the type of a Node; the type is just a constant int that is used to identify different types of Nodes, for example the Node.ELEMENT_NODE type identifies a Node to be an Element. You can use the getNodeValue() method to get the textual data stored inside a Node.

The Node interface has methods that allow the traversal of a Node tree. The getChildNodes() method is useful for getting all the elements inside a Node. This method returns all Nodes (if they exist) in an object that is a container for Node objects; this object implements the NodeList interface. NodeList is an iterator for a list of Nodes. Figure 5 illustrates how NodeList can be used.