Translate SAX events to a DOM tree

Posted by Florent Georges, on 2006-08-24, in dom and sax.

I had to pass the XML document provided by a piece of software to an other piece of software. The first one provides the document as SAX events. But the second one expects a DOM Document. So here is a SAX-events-to-DOM-Document translator:

public class SaxToDom
{
    public SaxToDom(XMLReader reader, InputSource input) {
        myReader = reader;
        myInput  = input;
    }

    public Document makeDom() {
        Document doc = null;
        try {
            // Find the implementation
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder        builder = factory.newDocumentBuilder();
            DOMImplementation      impl    = builder.getDOMImplementation();

            // Create the document
            doc = impl.createDocument(null, null, null);

            // The Handlers and the actual building
            SaxToDomHandler handlers = new SaxToDomHandler(doc);
            myReader.setContentHandler(handlers);
            myReader.setErrorHandler(handlers);
            myReader.parse(myInput);
        }
        // For the catch handlers below, use your usual logging facilities.
        catch (DOMException e) {
            System.err.println(e); 
        }
        catch (ParserConfigurationException e) {
            System.err.println(e); 
        }
        catch (SAXException e) {
            System.err.println(e); 
        }
        catch (IOException e) {
            System.err.println(e); 
        }
        return doc;
    }

    private XMLReader   myReader;
    private InputSource myInput;
}


class SaxToDomHandler
    extends DefaultHandler
{
    public SaxToDomHandler(Document doc) {
        myDoc         = doc;
        myCurrentNode = myDoc;
    }

    // Add it in the DOM tree, at the right place.
    public void startElement(String uri, String name, String qName, Attributes attrs) {
        // Create the element.
        Element elem = myDoc.createElementNS(uri, qName);
        // Add each attribute.
        for ( int i = 0; i < attrs.getLength(); ++i ) {
            String ns_uri = attrs.getURI(i);
            String qname  = attrs.getQName(i);
            String value  = attrs.getValue(i);
            Attr   attr   = myDoc.createAttributeNS(ns_uri, qname);
            attr.setValue(value);
            elem.setAttributeNodeNS(attr);
        }
        // Actually add it in the tree, and adjust the right place.
        myCurrentNode.appendChild(elem);
        myCurrentNode = elem;
    }

    // Adjust the current place for subsequent additions.
    public void endElement(String uri, String name, String qName) {
        myCurrentNode = myCurrentNode.getParentNode();
    }

    // Add a new text node in the DOM tree, at the right place.
    public void characters(char[] ch, int start, int length) {
        String str  = new String(ch, start, length);
        Text   text = myDoc.createTextNode(str);
        myCurrentNode.appendChild(text);
    }

    // Add a new text node in the DOM tree, at the right place.
    public void ignorableWhitespace(char[] ch, int start, int length) {
        String str  = new String(ch, start, length);
        Text   text = myDoc.createTextNode(str);
        myCurrentNode.appendChild(text);
    }

    // Add a new text PI in the DOM tree, at the right place.
    public void processingInstruction(String target, String data) {
        ProcessingInstruction pi = myDoc.createProcessingInstruction(target, data);
        myCurrentNode.appendChild(pi);
    }

    // For the handlers below, use your usual logging facilities.
    public void error(SAXParseException e) {
        System.err.println("Erreur non fatale  (ligne " + e.getLineNumber() + ", col " +
                           e.getColumnNumber() + ") : " + e.getMessage());
    }

    public void fatalError(SAXParseException e) {
        System.err.println("Erreur fatale : " + e.getMessage());
    }

    public void warning(SAXParseException e) {
        System.err.println("Warning : " + e.getMessage());
    }

    private Document myDoc;
    private Node     myCurrentNode;
}

Posted by Florent Georges, on 2006-08-24T15:43:00, tags: dom and sax.