So far, I’ve deliberately avoided the crucial question of how one creates a DOMImplementation object in the first place. Since DOMImplementation is an interface, not a class, it cannot be instantiated directly through its own constructor. Instead you have to build it in one of three ways:
Construct the implementation specific class
Use the JAXP DocumentBuilder factory class.
Use the DOM Level 3 DOMImplementationRegistry factory class.
Directly constructing an instance of the vendor class that implements DOMImplementation is the simplest of the three alternatives. However, the name of this class and how it’s created vary from one implementation to the next. For example, in Xerces the org.apache.xerces.dom.DOMImplementationImpl singleton class implements the DOMImplementation interface. The singleton object is retrieved via the getDOMImplementation() factory method like this:
DOMImplementation impl = DOMImplementationImpl.getDOMImplementation();
However, if you were to switch to a different implementation, you’d need to change your source code and recompile. For example, in the Oracle XML parser for Java, oracle.xml.parser.v2.XMLDOMImplementation class implements the DOMImplementation interface and instances of this class are created with a no-args constructor, like this:
DOMImplementation impl = new XMLDOMImplementation();
In both cases, the implementation specific object is assigned to a variable of type DOMImplementation. This allows the compiler to make sure you don’t accidentally use any implementation-specific methods in the object, or tie the code too tightly to one vendor. The implementation-dependent code should be limited to this one line.
The JAXP DocumentBuilder class introduced in the last chapter has a getDOMImplementation() method that can locate a local DOMImplementation class.
public abstract DOMImplementation getDOMImplementation();
For example, this code fragment uses JAXP to create a new SVG Document object in memory:
try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); DOMImplementation impl = builder.getDOMImplementation(); DocumentType svgDOCTYPE = impl.createDocumentType("svg", "-//W3C//DTD SVG 1.0//EN", "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"); Document svgDoc = impl.createDocument( "http://www.w3.org/2000/svg", "svg", svgDOCTYPE ); // work with the document... } catch (FactoryConfigurationError e) { System.out.println( "Could not locate a JAXP DocumentBuilderFactory class"); } catch (ParserConfigurationException e) { System.out.println( "Could not locate a JAXP DocumentBuilder class"); }
If you only want to create a new Document, then DocumentBuilder also has a newDocument() method that shortcuts the DOMImplementation class:
public abstract Document newDocument();
However, this method does not properly set a root element. Thus the documents created by newDocument() are at least initially malformed; and therefore I recommend that you don’t use this method. Just use JAXP to retrieve a DOMImplementation object and use its createDocument() method instead.
The specific implementation JAXP chooses is determined in the same way as described for locating a parser in the last chapter. That is, first JAXP reads the javax.xml.parsers.DocumentBuilderFactory system property, then the lib/jaxp.properties file, then the META-INF/services/javax.xml.parsers.DocumentBuilderFactory file in all JAR files available to the runtime, and then finally a fallback class hardcoded into the JAXP implementation.
The final option for locating the DOMImplementation is new in DOM Level 3 and only supported by Xerces 2 so far. This is the DOMImplementationRegistry class shown in Example 10.2.
Example 10.2. The DOMImplementationRegistry class
package org.w3c.dom; public class DOMImplementationRegistry { // The system property that specifies DOMImplementationSource // class names. public static String PROPERTY = "org.w3c.dom.DOMImplementationSourceList"; public static DOMImplementation getDOMImplementation( String features) throws ClassNotFoundException, InstantiationException, IllegalAccessException; public static void addSource(DOMImplementationSource s) throws ClassNotFoundException, InstantiationException, IllegalAccessException; }
The getDOMImplementation() method returns a DOMImplementation object that supports the features given in the argument, or null if no such implementation can be found. For example, this code fragment requests a DOMImplementation that supports XML DOM Level 1, any version of the traversal module, and DOM Level 2 events:
try { DOMImplementation impl = DOMImplementationRegistry .getDOMImplementation("XML 1.0 Traversal Events 2.0"); if (impl != null) { DocumentType svgDOCTYPE = impl.createDocumentType("svg", "-//W3C//DTD SVG 1.0//EN", "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"); Document svgDoc = impl.createDocument( "http://www.w3.org/2000/svg", "svg", svgDOCTYPE ); // work with the document... } } catch (Exception e) { System.out.println(e); }
Be sure to check whether the implementation returned is null before using it. Many installations may not be able to support all the features you ask for.
DOMImplementationRegistry searches for DOMImplementation classes by looking at the value of the org.w3c.dom.DOMImplementationSourceList Java system property. This property should contain a white space separated list of DOMImplementationSource classes on the local system. This interface is summarized in Example 10.3.
Example 10.3. The DOMImplementationSource interface
package org.w3c.dom; public interface DOMImplementationSource { public DOMImplementation getDOMImplementation(String features); }
DOMImplementationRegistry.getDOMImplementation() queries each source for its DOMImplementation. The double indirection (listing DOMImplementationSource classes rather than DOMImplementation classes) is necessary to allow DOMImplementationRegistry.getDOMImplementation() to return different classes of objects depending on which combination of features are requested.
The three exceptions that getDOMImplementation() throws— ClassNotFoundException, InstantiationException, and IllegalAccessException— shouldn’t be very common. The only way any of these can be thrown is if the org.w3c.dom.DOMImplementationSourceList system property includes the name of a class that can’t be found or one that is not a conforming instance of DOMImplementationSource.
However, like the other DOM Level 3 material discussed in this book, all of this is on the wrong side of the bleeding edge and cannot be expected to work in most existing implementations.
Copyright 2001, 2002 Elliotte Rusty Harold | elharo@metalab.unc.edu | Last Modified January 13, 2002 |
Up To Cafe con Leche |