SAXAdapter.java

  1. /*
  2.  * SAXAdapter
  3.  *
  4.  * $Id$
  5.  * $HeadURL$
  6.  */
  7. package gov.usgs.util;

  8. import java.io.InputStream;
  9. import java.io.ByteArrayInputStream;
  10. import java.util.LinkedList;

  11. import javax.xml.parsers.SAXParser;
  12. import javax.xml.parsers.SAXParserFactory;

  13. import org.xml.sax.Attributes;
  14. import org.xml.sax.InputSource;
  15. import org.xml.sax.SAXException;
  16. import org.xml.sax.XMLReader;
  17. import org.xml.sax.helpers.DefaultHandler;


  18. /**
  19.  * SAXAdapter is a sax handler that accumulates element content, which is a
  20.  * common sax handler task.
  21.  *
  22.  * Users should be cautious because this in some ways removes efficiency gained
  23.  * by handling streaming events, because element content is being buffered. One
  24.  * buffer for each element nesting is maintained, so this works best for shallow
  25.  * documents, whose elements contain little content.
  26.  */
  27. public class SAXAdapter extends DefaultHandler {

  28.     /** Buffers for element content, since it may be delivered in pieces. */
  29.     private LinkedList<StringBuffer> buffers = new LinkedList<StringBuffer>();

  30.     /**
  31.      * SAXAdapter start element handler.
  32.      *
  33.      * @param uri
  34.      *            element uri.
  35.      * @param localName
  36.      *            element localName.
  37.      * @param qName
  38.      *            element qName.
  39.      * @param attributes
  40.      *            element attributes.
  41.      * @throws SAXException
  42.      *             if there is an error.
  43.      */
  44.     public void onStartElement(final String uri, final String localName,
  45.             final String qName, final Attributes attributes)
  46.             throws SAXException {
  47.     }

  48.     /**
  49.      * SAXAdapter end element handler. Content only includes characters that
  50.      * were read from this element, NOT any characters from child elements.
  51.      *
  52.      * @param uri
  53.      *            element uri.
  54.      * @param localName
  55.      *            element localName.
  56.      * @param qName
  57.      *            element qName.
  58.      * @param content
  59.      *            element content.
  60.      * @throws SAXException
  61.      *             if onEndElement throws a SAXException.
  62.      */
  63.     public void onEndElement(final String uri, final String localName,
  64.             final String qName, final String content) throws SAXException {
  65.     }

  66.     /**
  67.      * Override DefaultHandler startElement. Adds a new element content buffer
  68.      * and calls onStartElement.
  69.      *
  70.      * @param uri
  71.      *            element uri.
  72.      * @param localName
  73.      *            element localName.
  74.      * @param qName
  75.      *            element qName.
  76.      * @param attributes
  77.      *            element attributes.
  78.      * @throws SAXException
  79.      *             if onStartElement throws a SAXException.
  80.      */
  81.     public final void startElement(final String uri, final String localName,
  82.             final String qName, final Attributes attributes)
  83.             throws SAXException {
  84.         buffers.add(new StringBuffer());
  85.         onStartElement(uri, localName, qName, attributes);
  86.     }

  87.     /**
  88.      * Override DefaultHandler endElement. Retrieves element content buffer and
  89.      * passes it to onEndElement.
  90.      *
  91.      * @param uri
  92.      *            element uri.
  93.      * @param localName
  94.      *            element localName.
  95.      * @param qName
  96.      *            element qName.
  97.      * @throws SAXException
  98.      *             if onEndElement throws a SAXException.
  99.      */
  100.     public final void endElement(final String uri, final String localName,
  101.             final String qName) throws SAXException {
  102.         String elementContent = buffers.removeLast().toString();
  103.         onEndElement(uri, localName, qName, elementContent);
  104.     }

  105.     /**
  106.      * Override DefaultHandler characters. Appends content to current element
  107.      * buffer, or skips if before first element.
  108.      *
  109.      * @param ch
  110.      *            content.
  111.      * @param start
  112.      *            position in content to read.
  113.      * @param length
  114.      *            lenth of content to read.
  115.      * @throws SAXException
  116.      *             never.
  117.      */
  118.     public final void characters(final char[] ch, final int start,
  119.             final int length) throws SAXException {
  120.         if (buffers.size() > 0) {
  121.             buffers.getLast().append(ch, start, length);
  122.         }
  123.     }

  124.     /**
  125.      * Use this handler to parse a string. Wraps string bytes in a
  126.      * ByteArrayInputStream.
  127.      *
  128.      * @param xml
  129.      *            string containing xml to parse.
  130.      * @return any exception that occurs while parsing, or null if no exceptions
  131.      *         occur.
  132.      */
  133.     public final Exception parse(final String xml) {
  134.         return parse(new ByteArrayInputStream(xml.getBytes()));
  135.     }

  136.     /**
  137.      * Use this handler to parse an input stream. Uses self as a content and
  138.      * error handler in an XMLReader. If an error occurs, use getException to
  139.      * retrieve the error.
  140.      *
  141.      * @param xml
  142.      *            input stream of xml to parse.
  143.      * @return any exception that occurs while parsing, or null if no exceptions
  144.      *         occur.
  145.      */
  146.     public final Exception parse(InputStream xml) {
  147.         try {
  148.             SAXParserFactory spf = SAXParserFactory.newInstance();
  149.             spf.setNamespaceAware(true);
  150.             SAXParser sp = spf.newSAXParser();
  151.             XMLReader xr = sp.getXMLReader();
  152.             xr.setContentHandler(this);
  153.             xr.setErrorHandler(this);
  154.             xr.parse(new InputSource(xml));
  155.             return null;
  156.         } catch (Exception e) {
  157.             return e;
  158.         } finally {
  159.             StreamUtils.closeStream(xml);
  160.         }
  161.     }

  162. }