All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javanet.staxutils.XMLStreamReaderToContentHandler Maven / Gradle / Ivy

The newest version!
/* $Id: XMLStreamReaderToContentHandler.java,v 1.6 2006/01/23 18:50:02 sandoz Exp $
 *
 * Copyright (c) 2004, Sun Microsystems, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above
 *      copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *     * Neither the name of Sun Microsystems, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package javanet.staxutils;

import javanet.staxutils.helpers.XMLFilterImplEx;

import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/**
 * This is a simple utility class that adapts StAX events from an
 * {@link javax.xml.stream.XMLStreamReader} to SAX events on a
 * {@link org.xml.sax.ContentHandler}, bridging between the two parser
 * technologies.
 *
 * @author [email protected]
 * @version 1.0
 */
public class XMLStreamReaderToContentHandler implements StAXReaderToContentHandler {

  // StAX event source
  private final XMLStreamReader staxStreamReader;

  // SAX event sinks
  private XMLFilterImplEx filter;

  /**
   * Construct a new StAX to SAX adapter that will convert a StAX event stream
   * into a SAX event stream.
   * 
   * @param staxCore
   *          StAX event source
   * @param filter
   *          SAX event sink
   */
  public XMLStreamReaderToContentHandler(XMLStreamReader staxCore, XMLFilterImplEx filter) {
    staxStreamReader = staxCore;

    this.filter = filter;
  }

  /*
   * @see StAXReaderToContentHandler#bridge()
   */
  public void bridge() throws XMLStreamException {

    try {
      // remembers the nest level of elements to know when we are done.
      int depth = 0;
      boolean isDocument = false;

      handleStartDocument();

      // if the parser is at the start document, procees any comments or
      // PIs
      int event = staxStreamReader.getEventType();
      if (event == XMLStreamConstants.START_DOCUMENT) {
        isDocument = true;
        event = staxStreamReader.next();
        while (event != XMLStreamConstants.START_ELEMENT) {
          switch (event) {
          case XMLStreamConstants.COMMENT:
            handleComment();
            break;
          case XMLStreamConstants.PROCESSING_INSTRUCTION:
            handlePI();
            break;
          }
          event = staxStreamReader.next();
        }
        ;
      }

      if (event != XMLStreamConstants.START_ELEMENT)
        throw new IllegalStateException("The current event is not START_ELEMENT\n but" + event);

      do {
        // These are all of the events listed in the javadoc for
        // XMLEvent.
        // The spec only really describes 11 of them.
        switch (event) {
        case XMLStreamConstants.START_ELEMENT:
          depth++;
          handleStartElement();
          break;
        case XMLStreamConstants.END_ELEMENT:
          handleEndElement();
          depth--;
          break;
        case XMLStreamConstants.CHARACTERS:
          handleCharacters();
          break;
        case XMLStreamConstants.ENTITY_REFERENCE:
          handleEntityReference();
          break;
        case XMLStreamConstants.PROCESSING_INSTRUCTION:
          handlePI();
          break;
        case XMLStreamConstants.COMMENT:
          handleComment();
          break;
        case XMLStreamConstants.DTD:
          handleDTD();
          break;
        case XMLStreamConstants.ATTRIBUTE:
          handleAttribute();
          break;
        case XMLStreamConstants.NAMESPACE:
          handleNamespace();
          break;
        case XMLStreamConstants.CDATA:
          handleCDATA();
          break;
        case XMLStreamConstants.ENTITY_DECLARATION:
          handleEntityDecl();
          break;
        case XMLStreamConstants.NOTATION_DECLARATION:
          handleNotationDecl();
          break;
        case XMLStreamConstants.SPACE:
          handleSpace();
          break;
        default:
          throw new InternalError("processing event: " + event);
        }

        event = staxStreamReader.next();
      } while (depth != 0);

      // procees any remaining comments or PIs
      if (isDocument) {
        while (event != XMLStreamConstants.END_DOCUMENT) {
          switch (event) {
          case XMLStreamConstants.COMMENT:
            handleComment();
            break;
          case XMLStreamConstants.PROCESSING_INSTRUCTION:
            handlePI();
            break;
          }
          event = staxStreamReader.next();
        }
      }

      handleEndDocument();
    } catch (SAXException e) {
      throw new XMLStreamException(e);
    }
  }

  private void handleEndDocument() throws SAXException {
    filter.endDocument();
  }

  private void handleStartDocument() throws SAXException {
    final Location location = staxStreamReader.getLocation();
    if (location != null) {
      filter.setDocumentLocator(new Locator() {
        public int getColumnNumber() {
          return location.getColumnNumber();
        }

        public int getLineNumber() {
          return location.getLineNumber();
        }

        public String getPublicId() {
          return location.getPublicId();
        }

        public String getSystemId() {
          return location.getSystemId();
        }
      });
    } else {
      filter.setDocumentLocator(new DummyLocator());
    }
    filter.startDocument();
  }

  private void handlePI() throws XMLStreamException {
    try {
      filter.processingInstruction(staxStreamReader.getPITarget(), staxStreamReader.getPIData());
    } catch (SAXException e) {
      throw new XMLStreamException(e);
    }
  }

  private void handleCharacters() throws XMLStreamException {

    // workaround for bugid 5046319 - switch over to commented section
    // below when it is fixed.
    int textLength = staxStreamReader.getTextLength();
    int textStart = staxStreamReader.getTextStart();
    char[] chars = new char[textLength];

    staxStreamReader.getTextCharacters(textStart, chars, 0, textLength);

    try {
      filter.characters(chars, 0, chars.length);
    } catch (SAXException e) {
      throw new XMLStreamException(e);
    }

    // int start = 0;
    // int len;
    // do {
    // len = staxStreamReader.getTextCharacters(start, buf, 0, buf.length);
    // start += len;
    // try {
    // filter.characters(buf, 0, len);
    // } catch (SAXException e) {
    // throw new XMLStreamException(e);
    // }
    // } while (len == buf.length);
  }

  private void handleEndElement() throws XMLStreamException {
    QName qName = staxStreamReader.getName();

    try {
      // fire endElement
      String prefix = qName.getPrefix();
      String rawname;
      if (prefix == null || prefix.length() == 0)
        rawname = qName.getLocalPart();
      else
        rawname = prefix + ':' + qName.getLocalPart();

      filter.endElement(qName.getNamespaceURI(), qName.getLocalPart(), rawname);

      // end namespace bindings
      int nsCount = staxStreamReader.getNamespaceCount();
      for (int i = nsCount - 1; i >= 0; i--) {
        String nsprefix = staxStreamReader.getNamespacePrefix(i);
        if (nsprefix == null) { // true for default namespace
          nsprefix = "";
        }
        filter.endPrefixMapping(nsprefix);
      }
    } catch (SAXException e) {
      throw new XMLStreamException(e);
    }
  }

  private void handleStartElement() throws XMLStreamException {

    try {
      // start namespace bindings
      int nsCount = staxStreamReader.getNamespaceCount();
      for (int i = 0; i < nsCount; i++) {
        String uri = staxStreamReader.getNamespaceURI(i);
        if (uri == null) {
          uri = "";
        }
        String prefix = staxStreamReader.getNamespacePrefix(i);
        if (prefix == null) { // true for default namespace
          prefix = "";
        }
        filter.startPrefixMapping(prefix, uri);
      }

      // fire startElement
      QName qName = staxStreamReader.getName();
      String prefix = qName.getPrefix();
      String rawname;
      if (prefix == null || prefix.length() == 0)
        rawname = qName.getLocalPart();
      else
        rawname = prefix + ':' + qName.getLocalPart();
      Attributes attrs = getAttributes();
      filter.startElement(qName.getNamespaceURI(), qName.getLocalPart(), rawname, attrs);
    } catch (SAXException e) {
      throw new XMLStreamException(e);
    }
  }

  /**
   * Get the attributes associated with the given START_ELEMENT or ATTRIBUTE
   * StAXevent.
   * 
   * @return the StAX attributes converted to an org.xml.sax.Attributes
   */
  private Attributes getAttributes() {
    AttributesImpl attrs = new AttributesImpl();

    int eventType = staxStreamReader.getEventType();
    if (eventType != XMLStreamConstants.ATTRIBUTE && eventType != XMLStreamConstants.START_ELEMENT) {
      throw new InternalError("getAttributes() attempting to process: " + eventType);
    }

    // Add namspace declarations if required
    if (filter.getNamespacePrefixes()) {
      for (int i = 0; i < staxStreamReader.getNamespaceCount(); i++) {
        String uri = staxStreamReader.getNamespaceURI(i);
        if (uri == null)
          uri = "";

        String prefix = staxStreamReader.getNamespacePrefix(i);
        if (prefix == null)
          prefix = "";

        String qName = "xmlns";
        if (prefix.length() == 0) {
          prefix = qName;
        } else {
          qName = qName + ':' + prefix;
        }
        attrs.addAttribute("http://www.w3.org/2000/xmlns/", prefix, qName, "CDATA", uri);
      }
    }

    // gather non-namespace attrs
    for (int i = 0; i < staxStreamReader.getAttributeCount(); i++) {
      String uri = staxStreamReader.getAttributeNamespace(i);
      if (uri == null)
        uri = "";
      String localName = staxStreamReader.getAttributeLocalName(i);
      String prefix = staxStreamReader.getAttributePrefix(i);
      String qName;
      if (prefix == null || prefix.length() == 0)
        qName = localName;
      else
        qName = prefix + ':' + localName;
      String type = staxStreamReader.getAttributeType(i);
      String value = staxStreamReader.getAttributeValue(i);

      attrs.addAttribute(uri, localName, qName, type, value);
    }

    return attrs;
  }

  private void handleNamespace() {
    // no-op ???
    // namespace events don't normally occur outside of a startElement
    // or endElement
  }

  private void handleAttribute() {
    // no-op ???
    // attribute events don't normally occur outside of a startElement
    // or endElement
  }

  private void handleDTD() {
    // no-op ???
    // it seems like we need to pass this info along, but how?
  }

  private void handleComment() throws XMLStreamException {
    int textLength = staxStreamReader.getTextLength();
    int textStart = staxStreamReader.getTextStart();
    char[] chars = new char[textLength];

    staxStreamReader.getTextCharacters(textStart, chars, 0, textLength);

    try {
      filter.comment(chars, 0, textLength);
    } catch (SAXException e) {
      throw new XMLStreamException(e);
    }
  }

  private void handleEntityReference() {
    // no-op ???
  }

  private void handleSpace() {
    // no-op ???
    // this event is listed in the javadoc, but not in the spec.
  }

  private void handleNotationDecl() {
    // no-op ???
    // this event is listed in the javadoc, but not in the spec.
  }

  private void handleEntityDecl() {
    // no-op ???
    // this event is listed in the javadoc, but not in the spec.
  }

  private void handleCDATA() {
    // no-op ???
    // this event is listed in the javadoc, but not in the spec.
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy