    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: XML in Applications II DOM - the Document Object
Model</title>
        <link>https://members.accu.org/index.php/journals/500</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">Overload Journal #36 - Mar 2000 + Design of applications and programs</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c168/">36</a>
                    (7)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c67/">Design</a>
                    (236)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c168-67/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c168+67/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;XML in Applications II DOM - the Document Object
Model</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 26 March 2000 17:50:56 +01:00 or Sun, 26 March 2000 17:50:56 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e18" id="d0e18"></a></h2>
</div>
<p>In the first part of this series, I introduced SAX, the Simple
API for XML. SAX is an event based API, and is best suited for
reading XML once only (our example was a data import). But what if
you want to read, alter and save your XML in the course of your
application? This is where the DOM fits in. This article will
describe DOM, how it came to be and how to use it.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e22" id="d0e22"></a>A brief history
of DOM</h2>
</div>
<p>The Document Object Model is a platform- and language-neutral
interface that will allow programs and scripts to dynamically
access and update the content, structure and style of documents.
The document can be further processed and the results of that
processing can be incorporated back into the presented page. This
is an overview of DOM-related materials here at W3C and around the
web.</p>
<p>DOM started life in September 1997 as a W3C (World Wide Web
Consortium) requirements publication. From an XML parsing
perspective, the most important requirements are:</p>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e29" id="d0e29"></a>General</h3>
</div>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>The Object Model can be used to construct and deconstruct the
document.</p>
</li>
<li>
<p>It must be possible to read in a document and write out a
structurally identical document to disk (both documents can be
represented by the same raw structural model).</p>
</li>
</ul>
</div>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e39" id="d0e39"></a>Document
Manipulation</h3>
</div>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>There will be a way to add, remove and change elements and/or
tags (if permitted by the Document Type Definition and not
precluded by security or validity considerations) in the document
structure.</p>
</li>
<li>
<p>There will be a way to add, remove and change attributes (if
permitted by the Document Type Definition and not precluded by
security or validity considerations) in the document structure.</p>
</li>
<li>
<p>Operations must restore consistency before they return.</p>
</li>
</ul>
</div>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e52" id="d0e52"></a>Content
Manipulation</h3>
</div>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>There will be a way to determine the containing element from any
text part of the document.</p>
</li>
<li>
<p>There will be a way to manipulate (add, change, delete)
content.</p>
</li>
<li>
<p>There will be a way to navigate content.</p>
</li>
</ul>
</div>
<p>After a few drafts, the DOM Level 1 Specification became a W3C
recommendation in October 1998. So what does the &quot;Level 1&quot; bit
mean? The DOM working group plan to release their work in stages.
Level one concentrates on the actual core, HTML, and XML document
models. It contains functionality for document navigation and
manipulation.</p>
<p>Level two will include a style sheet object model, and define
functionality for manipulating the style information attached to a
document. It will also allow rich queries of the document and
define some event models, and provide support for XML
namespaces.</p>
<p>Further levels will specify some interface with the possibly
underlying window system, including some ways to prompt the user.
They will also contain functions to manipulate the document's DTD.
Finally, they will include some security models.</p>
<p>On 23 September 1999, the working group released the first
version of the working draft of the level 2 specification.</p>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e73" id=
"d0e73"></a>org.w3c.dom</h2>
</div>
<p>Like SAX, DOM is only an interface specification. It is up to
vendors to provide implementations of the interfaces. Fortunately,
many of the SAX based XML parser implementations also provide a DOM
interface. I will be using the XML4J from IBM Alphaworks for the
examples in this article.</p>
<p>Access to the DOM is through the <span class=
"bold"><b>Document</b></span> interface. The Document object
represents the root of the document tree. The Document interface
contains a number of factory method for creating elements,
attributes, comments and processing instructions. The object model
is often implied to have a tree structure. Although W3C were very
cautious not to use the word tree (in case they were seen to be
mandating implementation details), DOM does imply a logical tree
structure even if the implementer has chosen a different
structure.</p>
<p>All nodes on the document tree implement the <span class=
"bold"><b>Node</b></span> interface (Document inherits from the
Node interface). The <span class="bold"><b>Node</b></span>
interface provides for navigation between child, parent and sibling
nodes, as well as a direct link to the owning Document object via
the <span class="bold"><b>getOwnerDocument()</b></span> method. A
Node object can be made to reveal the type of node it represents
via the <span class="bold"><b>getNodeType()</b></span> method. The
table on the next page provides a mapping from XML terminology to
the node types defined on the Node interface.</p>
<p>Each of the node types has a corresponding class type whose
interface extends Node. The Node object can be cast to its
corresponding type class. For example:</p>
<div class="informaltable">
<table border="1" cellspacing="0">
&lt;colgroup&gt;
&lt;col&gt;
&lt;col&gt;&lt;/colgroup&gt;
&lt;thead&gt;
<tr>
<th>XML entity</th>
<th>org.w3c.dom.Node type</th>
</tr>
&lt;/thead&gt;
&lt;tbody&gt;
<tr>
<td>Root element</td>
<td>DOCUMENT_NODE</td>
</tr>
<tr>
<td>Tag / element &lt;..&gt; or &lt;/..&gt;</td>
<td>ELEMENT_NODE</td>
</tr>
<tr>
<td>Element Attributes</td>
<td>ATTRIBUTE_NODE</td>
</tr>
<tr>
<td>Text</td>
<td>CDATA_SECTION_NODE or TEXT_NODE</td>
</tr>
<tr>
<td>XML processinginstruction &lt;? &hellip; ?&gt;</td>
<td>PROCESSING_INSTRUCTION_NODE</td>
</tr>
<tr>
<td>Entity references</td>
<td>ENTITY_REFERENCE_NODE</td>
</tr>
&lt;/tbody&gt;
</table>
</div>
<pre class="programlisting">
public Document getDocument(Node node)
{
  Document doc = null;
  if (node.getType() == Node.DOCUMENT_NODE)
  {
    // if we call getOwnerDocument on the document object it returns null
  doc = (Document) node;
  }
  else
  {
    doc = node.getOwnerDocument();
  }
  return doc;
}
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e140" id="d0e140"></a>Using DOM to
handle XML</h2>
</div>
<p>As I stated at the beginning of the article, DOM is better
suited to read / alter / write XML than SAX is. The example we will
be using is that of an application's properties file written in
XML.</p>
<p>Since there are numerous XML parsers that support the DOM
interfaces, we're going to use IBM Alphaworks' XML4J parser to
construct the object model, and write our own code to manipulate
and write back our model to XML. Since parsing/loading and saving
back XML files is common behaviour for a DOM application, it makes
sense to factor that behaviour out to a common class. I've written
such a class, called <span class=
"bold"><b>DOMManager</b></span>:</p>
<pre class="programlisting">
package org.accu.cornish.xml.dom;

import org.w3c.dom.*;
import com.ibm.xml.dom.*;
import com.ibm.xml.parsers.DOMParser;
import java.io.IOException;
import java.io.PrintWriter;
import org.xml.sax.SAXException;

public class DOMManager
{
  private PrintWriter out = null;

  public DOMManager() {}

  public Document loadDocument(String uri)
    throws IOException
  {
//  this is all the code necessary to get the Document object from the URI
    DOMParser domParser = new DOMParser();
    Document doc;
    try {
      domParser.parse( uri );
      doc = domParser.getDocument(); 
  }
    catch (SAXException badCall) 
    {
// convert it into an IOException
      throw new IOException(&quot;Error parsing XML: &quot; + uri);
    }
    return doc;
  }

  public void setOutputTarget(PrintWriter output)
  {
    this.out = output;
  }
  public void saveDocument(Node node) throws java.io.IOException
  {
    if (this.out == null)
    {
      throw new IOException(&quot;No target identified for save&quot;);
    }
    print( node );
  }
  private void print(Node node) { /* see dom.DOMWriter in the IBM Samples */ }
}
</pre>
<p>The method print(Node node) was pinched in whole from IBM's
sample application DOMWriter, along with helper methods (normalize
and sortAttributes). The source code for DOMWriter is available
from the installation for XML4J.</p>
<p>Now, to write any application that needs to import and export
XML, you can have your Property manager class delegate your
Document class management to a DOMManager member.</p>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e156" id="d0e156"></a>Inheritance vs.
Delegation</h3>
</div>
<p>I originally designed <span class=
"bold"><b>DOMManager</b></span> to be a super class for DOM
manipulating classes to inherit from. After consideration, I've
realised that it is more useful to have your class to implement
<span class="bold"><b>DOMManager</b></span> as a private member
variable, and delegate calls to it. This changes the nature of
<span class="bold"><b>DOMManager</b></span> from being a behaviour
&quot;template&quot; to being a helper object. I can identify two very good
reasons to make this change of viewpoint:</p>
<p>We don't mix the loading/saving interface into our property
management interface.</p>
<p>Delegating to our member variable allows our class to manage the
lifetime of the DOM. This would allow us to implement alternative
memory management policies such as lazy evaluation or saving on a
separate thread behind the scenes.</p>
<p>A very simple Property manager class that echoes the document
back to the standard output has its relevant functionality shown
here.</p>
<pre class="programlisting">
import java.io.*;
public class PropertiesViewer {
  private DOMManager settings;
  private Document doc;
  private String inFile;
  ...
  public void printToSystemOut()
  {
    try
    {
      doc = settings.loadDocument(inFile);  // inherited
// change our output to be the System.out
      settings.setOutputTarget(new PrintWriter(System.out));
      settings.saveDocument(doc);             // inherited
    }
    catch (IOException ioe)
    {
      System.out.println(&quot;I/O Problem with &quot; + inFile);
    }
  }
}
</pre></div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e178" id="d0e178"></a>Editing
documents with DOM</h3>
</div>
<p>Now that we have a basic framework in place for loading / saving
our XML documents, we can proceed to a less trivial example.
Consider an application that has the following property file:</p>
<pre class="literallayout">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;domapp&gt;
    &lt;display&gt;
        &lt;default_scheme&gt;normal&lt;/default_scheme&gt;
        &lt;scheme name=&quot;normal&quot;&gt;
            &lt;normal&gt;black&lt;/normal&gt;
            &lt;error&gt;red&lt;/error&gt;
            &lt;background&gt;white&lt;/background&gt;
            &lt;highlight&gt;blue&lt;/highlight&gt;
            &lt;highlight_background&gt;green&lt;/highlight_background&gt;
        &lt;/scheme&gt;
        &lt;scheme name=&quot;weird&quot;&gt;
            &lt;normal&gt;yellow&lt;/normal&gt;
            &lt;error&gt;red&lt;/error&gt;
            &lt;background&gt;black&lt;/background&gt;
            &lt;highlight&gt;purple&lt;/highlight&gt;
            &lt;highlight_background&gt;grey&lt;/highlight_background&gt;
        &lt;/scheme&gt;
    &lt;/display&gt;
&lt;/domapp&gt;
</pre>
<p>Our application wants to encapsulate the properties as a Java
object. As an example of showing how to edit the DOM, we will
change the <span class="bold"><b>highlight_background</b></span> of
the &quot;normal&quot; scheme from green to yellow.</p>
<p>First, we create our <span class=
"bold"><b>DomAppProperties</b></span> class.</p>
<pre class="programlisting">
package org.accu.cornish.xml.dom;
import org.accu.cornish.xml.*;
import org.w3c.dom.*;
import java.io.*;
import java.util.Vector;

public class DomAppProperties {
    private String propertiesFile = &quot;D:\\xml\\domapp.properties&quot;;
    private DOMManager domManager;
    private Document doc;

    public DomAppProperties()
    {
        domManager = new DOMManager();
    }
    public void load()   { &hellip; }
    public void save()  { &hellip; }

    public boolean changeDisplaySchemeValue(String scheme,String name,String value)
    {
        if (doc == null)
        {
            System.err.println(&quot;Error:  no document node&quot;);
            return false;
        }
        try
        {
            Node schemeNode = this.getDisplaySchemeNode(scheme);
            Node node = this.findElement(schemeNode, name);
            this.setElementValue(node, value);
        }
        catch (BadXMLException bXML)
        {
            System.err.println(bXML.message());
        }
        return true;
    }

    private Node getRootElementNode() throws BadXMLException
    {
// start at the document node
// get the root element &lt;domapp&gt;
        Node node = doc.getDocumentElement();
        if ( !node.getNodeName().equals(&quot;domapp&quot;) )
        {
            throw new BadXMLException(&quot;Unexpected root node &lt;&quot;
                                    + node.getNodeName()
                                    + &quot;&gt;, was expecting &lt;domapp&gt;&quot;);
        }
        return node;
    }

    private Node getDisplayNode(Node rootElementNode) throws BadXMLException
    {
        Node node = null;
// verified node = &lt;domapp&gt;
// get the child element &lt;display&gt;
        NodeList children = rootElementNode.getChildNodes();
        for (int i = 0; i &lt; children.getLength(); ++i)
        {
            if (children.item(i).getNodeName().equals(&quot;display&quot;))
            {
                node = children.item(i);
            }
        }
        if (! node.getNodeName().equals(&quot;display&quot;) )
        {
            throw new BadXMLException(&quot;Unexpected structure, was expecting &quot;
                            + &quot;&lt;display&gt; after &lt;domapp&gt;&quot;);
        }
        return node;
    }

    private Node getDisplaySchemeNode(String schemeName) throws BadXMLException
    {
        Node node = getDisplayNode( getRootElementNode() );

// verified node = &lt;display&gt;
// get the children - can be &lt;default_scheme&gt; or &lt;scheme&gt;
        boolean bFound = false;
        NodeList children = node.getChildNodes();
        for (int i = 0; i &lt; children.getLength() &amp;&amp; !bFound; ++i)
        {
            if (children.item(i).getNodeName().equals(&quot;scheme&quot;))
            {
// we are in a &lt;scheme&gt; node - is it the right one?
//
// it's the one with with name attribute equal to the schemeName passed into this method
                NamedNodeMap attrs = children.item(i).getAttributes();
                Node attNode = null;

                if ( (attNode = attrs.getNamedItem(&quot;name&quot;)) == null)
                {
                    throw new BadXMLException(&quot;&lt;scheme&gt; node has no name attribute&quot;);
                }
                else
                {
// we're in the &lt;scheme name=&quot; node - check the value

                    if (attNode.getNodeValue().equals(schemeName))
                    {
                        // BINGO!
                        bFound = true;
                        node = children.item(i);
                    }
                }
            }   //if scheme
        }   // children of &lt;display&gt;
        children = null;
        if (! bFound )
        {
            throw new BadXMLException(&quot;Cannot find &lt;scheme name=\&quot;&quot;
                                        + schemeName + &quot;\&quot;&gt;&quot;);
        }
// return the node
        return node;
    }

    private Node findElement(Node node, String name)
    {
        Node returnNode = null;

        if (node.getNodeType() == Node.ELEMENT_NODE)
        {
            if (node.getNodeName().equals(name))
            {
                returnNode = node;
            }
            else
            {
// go through all the children

                NodeList children = node.getChildNodes();
                if (children != null)
                {
                    int len = children.getLength();
                    Node tempNode;

                    found: for (int i = 0; i &lt; len; ++i)
                    {
                        returnNode = findElement(children.item(i), name);
                        if (returnNode != null)
                        {
                            break found;  // from this for loop
                        }
                    }
                }
            }
        }
        return returnNode;
    }
    private void setElementValue(Node element, String newValue) {
        NodeList children = element.getChildNodes();
        if (children != null)
        {
            int len = children.getLength();
            for (int i = 0; i &lt; len; ++i)
            {
                if (children.item(i).getNodeType() == Node.TEXT_NODE)
                {
                    children.item(i).setNodeValue(newValue);
                }
            }
        }
    }
}
</pre>
<p>First note that there is no parser specific code in this class -
this is because we've hidden it all away in the <span class=
"bold"><b>DomManager</b></span> class. The <span class=
"bold"><b>load()</b></span> and <span class=
"bold"><b>save()</b></span> methods are trivial enough not to
detail them. The important public method is the <span class=
"bold"><b>ChangeDisplaySchemeValue(scheme, element,
value)</b></span> method. This method performs three distinct tasks
(each as private methods - highlighted in bold). First it finds the
appropriate <span class="bold"><b>&lt;scheme&gt; node</b></span>
(recall that our XML file can contain more than one scheme). Next,
the correct element in the scheme is identified. Finally, the new
value is set.</p>
<p>The private methods of the class give some useful examples of
processing with the DOM tree. Note that because I'm using elements
and values (tags and text) in my XML to represent the settings,
this shapes the <span class="bold"><b>setElementValue()</b></span>
method. If I had used tags with attributes, this method would need
to be implemented differently.</p>
<p>Now we need a harness to show the <span class=
"bold"><b>DomAppProperties</b></span> in action. For convenience,
I'll define a main method on the class.</p>
<pre class="programlisting">
    public static void main(String[] args)
    {
        DomAppProperties editor = new DomAppProperties();
        editor.load();
        editor.changeDisplaySchemeValue(&quot;normal&quot;, &quot;highlight_background&quot;, &quot;yellow&quot;);
        editor.changeDisplaySchemeValue(&quot;weird&quot;, &quot;normal&quot;, &quot;orange&quot;);
        editor.save();
    }
</pre>
<p>This is all we need to make our changes.</p>
<p>Of course, the <span class="bold"><b>DomAppProperties</b></span>
is a class of dubious usefulness - it doesn't even have methods to
report existing values. I hope it fulfills its intended purpose -
to demonstrate how to use DOM and DOM compliant parsers to
manipulate XML documents.</p>
<p>DOM provides quite a rich API for manipulating documents. Most
users would likely wrap it with an interface more useful to the
task at hand (e.g. property files). DOM parsers are best suited to
processing XML documents that need to be read (possibly more than
once) and may be subject to a non-trivial amount of manipulation.
DOM is definitely suited to recreating the XML document at a later
time. As you may recall from the previous article, SAX is better
suited to read-once, process immediately usage.</p>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e235" id="d0e235"></a>Free DOM
parsers</h2>
</div>
<p>There are a number of free XML Parsers that support the DOM
Level 1. Here are the main players:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>XML4J (IBM) - <a href=
"http://www.alphaworks.ibm.com/formula/xml" target=
"_top">http://www.alphaworks.ibm.com/formula/xml</a></p>
</li>
<li>
<p>Java Project X (Sun) - <a href=
"http://developer.java.sun.com/developer/earlyAccess/xml/index.html"
target=
"_top">http://developer.java.sun.com/developer/earlyAccess/xml/index.html</a></p>
</li>
<li>
<p>XML Parser for Java 2 (Oracle) - <a href=
"http://technet.oracle.com" target=
"_top">http://technet.oracle.com</a></p>
</li>
<li>
<p>Docuverse DOM SDK - this is a DOM implementation that can sit on
top of any SAX compliant parser - <a href=
"http://www.docuverse.com/domsdk/" target=
"_top">http://www.docuverse.com/domsdk/</a></p>
</li>
</ul>
</div>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e261" id="d0e261"></a>Further
References</h2>
</div>
<div class="bibliomixed">
<p class="bibliomixed">DOMit is an online utility for checking the
validity of your XML files. The idea is you paste your document
into the text pane, then hit the button to create a DOM
representation of your XML. Very useful <span class=
"bibliomisc"><a href=
"http://www.networking.ibm.com/xml/XmlValidatorForm.html" target=
"_top">http://www.networking.ibm.com/xml/XmlValidatorForm.html</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed">The World Wide Web Consortium DOM site -
<span class="bibliomisc"><a href="http://www.w3.org/DOM/" target=
"_top">http://www.w3.org/DOM/</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed">XML-Dev mailing list - <span class=
"bibliomisc"><tt class="email">&lt;<a href=
"mailto:xml-dev@ic.ac.uk">xml-dev@ic.ac.uk</a>&gt;</tt></span> and
a good XML site from Seybold and O'Reilly - <span class=
"bibliomisc"><a href="http://www.xml.com" target=
"_top">www.xml.com</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed">OASIS - <span class="bibliomisc"><a href=
"http://www.oasis-open.org/cover/cml.html" target=
"_top">www.oasis-open.org/cover/cml.html</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed">Another XML site (close links with OASIS) -
<span class="bibliomisc"><a href="http://www.xml.org" target=
"_top">www.xml.org</a></span></p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
