Parsing an XML Document in Java 6
Saturday, 19 July 2008 00:00

I often need to parse an XML String to navigate the DOM, but I always forget how to do it. I've written a short helper class that makes it easier for me to parse Strings, plus implement some basic thread safety around the DocumentBuilder class (which is not thread-safe).

The use of the ConcurrentLinkedQueue works like a very simple Object pool. I remove a DocumentBuilder from the queue to use it, and I add it back to the queue when done. The queue ensures the gets/puts are atomic, which ensures thread safety. For your own needs, you may opt to create a new DocumentBuilder each time you need to parse an XML String if you're not concerned about the overhead (which is minimal anyway).

package com.datajelly.xml;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class XmlParser {
  private static XmlParser instance = new XmlParser();

  private static ConcurrentLinkedQueue pool = new ConcurrentLinkedQueue();

  public static XmlParser getInstance() {
    return instance;
  }

  private XmlParser() {

  }

  public Document parse(String xml) {
    assert xml != null;
    return parse(new InputSource(new StringReader(xml)));
  }

  public Document parse(InputStream stream) {
    assert stream != null;
    return parse(new InputSource(stream));
  }

  private Document parse(InputSource source) {
    assert source != null;

    try {
      DocumentBuilder builder = pool.poll();
      if (builder == null) {
        builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
      }

      Document document = builder.parse(source);

      pool.add(builder);

      return document;
    } catch (ParserConfigurationException e) {
      throw new RuntimeException(e);
    } catch (SAXException e) {
      throw new RuntimeException(e);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
}