DOM Level 3


DOM Level 3

Elliotte Rusty Harold

Software Development 2004 West

Software Development 2004 West

Thursday, March 18, 2004

elharo@metalab.unc.edu

http://www.cafeconleche.org/


Outline


DOM Level 3

of all of the things the W3C has given us, the DOM is probably the one with the least value.

--Michael Brennan on the xml-dev mailing list


DOM Evolution


DOM Level 3 Core Changes


New methods in the Node interface


User Data

package org.w3c.dom;

public interface UserDataHandler {

  // OperationType
  public static final short NODE_CLONED   = 1;
  public static final short NODE_IMPORTED = 2;
  public static final short NODE_DELETED  = 3;
  public static final short NODE_RENAMED  = 4;
  public static final short NODE_ADOPTED  = 5;

  public void handle(short operation, String key, Object data, Node src, Node dst);

}

New methods in Entity


New methods in Document


DOMConfiguration


New methods in Text


New methods in Element


New methods in Attr


Bootstrapping


DOM3 Bootstrapping


Bootstrapping Example


DOM Error Handler Interfaces


The DOMErrorHandler Interface


The DOMError Interface

package org.w3c.dom;

public interface DOMError {
 
  public static final short SEVERITY_WARNING     = 0;
  public static final short SEVERITY_ERROR       = 1;
  public static final short SEVERITY_FATAL_ERROR = 2;

  public short      getSeverity();
  public String     getMessage();
  public String     getType();
  public Object     getRelatedException();
  public Object     getRelatedData();
  public DOMLocator getLocation();

}

The DOMLocator Interface


Load and Save


The DOM Process

  1. Library specific code creates a parser

  2. The parser parses the document and returns a DOM org.w3c.dom.Document object.

  3. The entire document is stored in memory.

  4. DOM methods and interfaces are used to extract data from this object


Parsing documents with DOM2

This program parses with Xerces. Other parsers are different.

import org.apache.xerces.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import java.io.*;

public class DOMParserMaker {

  public static void main(String[] args) {
     
    DOMParser parser = new DOMParser();
    
    for (int i = 0; i < args.length; i++) {
      try {
        parser.parse(args[i]);
        Document d = parser.getDocument();
      }
      catch (SAXException ex) {
        System.err.println(ex); 
      }
      catch (IOException ex) {
        System.err.println(ex); 
      }
      
    }
   
  }

}

Parsing documents with JAXP

import javax.xml.parsers.*; // JAXP
import org.xml.sax.SAXException;
import java.io.IOException;


public class JAXPParserMaker {

  public static void main(String[] args) {
     
    if (args.length <= 0) {
      System.out.println("Usage: java JAXPParserMaker URL");
      return;
    }
    String document = args[0];
    
    try {
      DocumentBuilderFactory factory 
       = DocumentBuilderFactory.newInstance();
      DocumentBuilder parser = factory.newDocumentBuilder();
      parser.parse(document); 
      System.out.println(document + " is well-formed.");
    }
    catch (SAXException e) {
      System.out.println(document + " is not well-formed.");
    }
    catch (IOException e) { 
      System.out.println(
       "Due to an IOException, the parser could not check " 
       + document
      ); 
    }
    catch (FactoryConfigurationError e) { 
      // JAXP suffers from excessive brain-damage caused by 
      // intellectual in-breeding at Sun. (Basically the Sun 
      // engineers spend way too much time talking to each other
      // and not nearly enough time talking to people outside 
      // Sun.) Fortunately, you can happily ignore most of the 
      // JAXP brain damage and not be any the poorer for it.
      
      // This, however, is one of the few problems you can't 
      // avoid if you're going to use JAXP at all. 
      // DocumentBuilderFactory.newInstance() should throw a 
      // ClassNotFoundException if it can't locate the factory
      // class. However, what it does throw is an Error,
      // specifically a FactoryConfigurationError. Very few 
      // programs are prepared to respond to errors as opposed
      // to exceptions. You should catch this error in your 
      // JAXP programs as quickly as possible even though the
      // compiler won't require you to, and you should 
      // never rethrow it or otherwise let it escape from the 
      // method that produced it. 
      System.out.println("Could not locate a factory class"); 
    }
    catch (ParserConfigurationException e) { 
      System.out.println("Could not locate a JAXP parser"); 
    }
   
  }

}

Parsing documents with DOM3

import org.w3c.dom.*;
import org.w3c.dom.ls.*;
import org.w3c.dom.bootstrap.*;


public class DOM3ParserMaker {

  public static void main(String[] args) 
    throws ClassNotFoundException, InstantiationException, IllegalAccessException {

    System.setProperty(DOMImplementationRegistry.PROPERTY,
      "org.apache.xerces.dom.DOMImplementationSourceImpl");
    DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
 
    DOMImplementation impl = registry.getDOMImplementation("LS-Load");
    if (impl == null) {
        System.err.println("Coudl not locate a DOM3 Parser");
        return;    
    }
    
    DOMImplementationLS implls = (DOMImplementationLS) impl;
    LSParser parser = implls.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS , null);

    for (int i = 0; i < args.length; i++) {
      try {
        Document d = parser.parseURI(args[i]);
      }
      catch (DOMException ex) {
        System.err.println(ex);
      }
      
    }

  }

}

Building Xerces with DOM3 Support


The Load and Save Package: org.w3c.dom.ls

DOMImplementationLS
A sub-interface of DOMImplementation that provides the factory methods for creating the objects required for loading and saving.
LSParser
A parser interface
LSInput
Encapsulate information about the source of the XML to be loaded, like SAX's InputSource
LSResourceResolver
During loading, provides a way for applications to redirect references to external entities.
LSParserFilter
Provide the ability to examine and optionally remove Element nodes as they are being processed during the parsing of a document. like SAX filters.
LSSerializer
An interface for serializing DOM documents onto a stream or string.
LSSerializerFilter
Provide the ability to examine and optionally remove or modify nodes as they are being output.
LSLoadEvent
A document has been completely loaded
LSProgressEvent
A document has been partially loaded

DOMImplementationLS


Creating DOMImplementationLS Objects

  1. Use the feature "LS" or "LS-Async" to find a DOMImplementation object that supports Load and Save.

  2. Cast the DOMImplementation object to DOMImplementationLS.

System.setProperty(DOMImplementationRegistry.PROPERTY,
  "org.apache.xerces.dom.DOMImplementationSourceImpl");
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
DOMImplementation impl = registry.getDOMImplementation("XML 1.0 LS 3.0");
  if (impl != null) {
    DOMImplementationLS implls = (DOMImplementationLS) impl;
    // ...
  }

LSParser


LSInput


LSOutput


LSResourceResolver


LSSerializer


Fibonacci with DOM3

import java.math.*;
import java.io.*;
import org.w3c.dom.*;
import org.w3c.dom.bootstrap.*;
import org.w3c.dom.ls.*;


public class FibonacciDOM3 {

  public static void main(String[] args) throws Exception {

      System.setProperty(DOMImplementationRegistry.PROPERTY,
        "org.apache.xerces.dom.DOMImplementationSourceImpl");
      DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
      DOMImplementation impl = registry.getDOMImplementation("XML 1.0 LS");
      if (impl == null) {
         System.err.println("Oops! Couln't find DOM3 implementation");   
         return;
      }
      Document fibonacci = impl.createDocument(null, "Fibonacci_Numbers", null );

      BigInteger low  = BigInteger.ZERO;
      BigInteger high = BigInteger.ONE;

      Element root = fibonacci.getDocumentElement();

      for (int i = 0; i <= 25; i++) {
        Element number = fibonacci.createElement("fibonacci");
        number.setAttribute("index", Integer.toString(i));
        Text text = fibonacci.createTextNode(low.toString());
        number.appendChild(text);
        root.appendChild(number);

        BigInteger temp = high;
        high = high.add(low);
        low = temp;
      }

      // Now that the document is created we need to *serialize* it
      DOMImplementationLS implls = (DOMImplementationLS) impl;
      LSSerializer serializer = implls.createLSSerializer();
      LSOutput output = implls.createLSOutput();
      output.setByteStream(new FileOutputStream("fibonacci_dom.xml"));
      
      serializer.write(fibonacci, output);

  }

}

LSParserFilter


LSSerializerFilter


Validation


DocumentEditVal


NodeEditVal


ElementEditVal


CharacterDataEditVal


XPath


Example


Querying with XPath

Document response;
// Initialize response object by parsing request...
String query = "/methodResponse/params/param/value/double";
if (impl.hasFeature("XPath", "3.0")) {
  XPathEvaluator evaluator = (XPathEvaluator) response;
  try {
    XPathResult index = evaluator.evaluate(query, response, 
     null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null)
    // work with the result...
  }
  catch (XPathException ex) {
    System.err.println(query 
     + " is not a correct XPath expression");
  }
  catch (DOMException ex) {
    System.err.println(ex);
  }
}

XPathEvaluator


XPathResult


Namespace Resolution


XPathExpression


XPathNamespace


To Learn More


Index | Cafe con Leche

Copyright 2000-2004 Elliotte Rusty Harold
elharo@metalab.unc.edu
Last Modified March 18, 2004