--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/DOM2SAX.java Thu Apr 12 08:38:26 2012 -0700
@@ -0,0 +1,485 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * $Id: DOM2SAX.java,v 1.2.4.1 2005/09/06 11:52:46 pvedula Exp $
+ */
+
+
+package com.sun.org.apache.xalan.internal.xsltc.trax;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Stack;
+import java.util.Vector;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl;
+import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary;
+
+/**
+ * @author G. Todd Miller
+ */
+public class DOM2SAX implements XMLReader, Locator {
+
+ private final static String EMPTYSTRING = "";
+ private static final String XMLNS_PREFIX = "xmlns";
+
+ private Node _dom = null;
+ private ContentHandler _sax = null;
+ private LexicalHandler _lex = null;
+ private SAXImpl _saxImpl = null;
+ private Hashtable _nsPrefixes = new Hashtable();
+
+ public DOM2SAX(Node root) {
+ _dom = root;
+ }
+
+ public ContentHandler getContentHandler() {
+ return _sax;
+ }
+
+ public void setContentHandler(ContentHandler handler) throws
+ NullPointerException
+ {
+ _sax = handler;
+ if (handler instanceof LexicalHandler) {
+ _lex = (LexicalHandler) handler;
+ }
+
+ if (handler instanceof SAXImpl) {
+ _saxImpl = (SAXImpl)handler;
+ }
+ }
+
+ /**
+ * Begin the scope of namespace prefix. Forward the event to the
+ * SAX handler only if the prefix is unknown or it is mapped to a
+ * different URI.
+ */
+ private boolean startPrefixMapping(String prefix, String uri)
+ throws SAXException
+ {
+ boolean pushed = true;
+ Stack uriStack = (Stack) _nsPrefixes.get(prefix);
+
+ if (uriStack != null) {
+ if (uriStack.isEmpty()) {
+ _sax.startPrefixMapping(prefix, uri);
+ uriStack.push(uri);
+ }
+ else {
+ final String lastUri = (String) uriStack.peek();
+ if (!lastUri.equals(uri)) {
+ _sax.startPrefixMapping(prefix, uri);
+ uriStack.push(uri);
+ }
+ else {
+ pushed = false;
+ }
+ }
+ }
+ else {
+ _sax.startPrefixMapping(prefix, uri);
+ _nsPrefixes.put(prefix, uriStack = new Stack());
+ uriStack.push(uri);
+ }
+ return pushed;
+ }
+
+ /*
+ * End the scope of a name prefix by popping it from the stack and
+ * passing the event to the SAX Handler.
+ */
+ private void endPrefixMapping(String prefix)
+ throws SAXException
+ {
+ final Stack uriStack = (Stack) _nsPrefixes.get(prefix);
+
+ if (uriStack != null) {
+ _sax.endPrefixMapping(prefix);
+ uriStack.pop();
+ }
+ }
+
+ /**
+ * If the DOM was created using a DOM 1.0 API, the local name may be
+ * null. If so, get the local name from the qualified name before
+ * generating the SAX event.
+ */
+ private static String getLocalName(Node node) {
+ final String localName = node.getLocalName();
+
+ if (localName == null) {
+ final String qname = node.getNodeName();
+ final int col = qname.lastIndexOf(':');
+ return (col > 0) ? qname.substring(col + 1) : qname;
+ }
+ return localName;
+ }
+
+ public void parse(InputSource unused) throws IOException, SAXException {
+ parse(_dom);
+ }
+
+ public void parse() throws IOException, SAXException {
+ if (_dom != null) {
+ boolean isIncomplete =
+ (_dom.getNodeType() != org.w3c.dom.Node.DOCUMENT_NODE);
+
+ if (isIncomplete) {
+ _sax.startDocument();
+ parse(_dom);
+ _sax.endDocument();
+ }
+ else {
+ parse(_dom);
+ }
+ }
+ }
+
+ /**
+ * Traverse the DOM and generate SAX events for a handler. A
+ * startElement() event passes all attributes, including namespace
+ * declarations.
+ */
+ private void parse(Node node) throws IOException, SAXException {
+ Node first = null;
+ if (node == null) return;
+
+ switch (node.getNodeType()) {
+ case Node.ATTRIBUTE_NODE: // handled by ELEMENT_NODE
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ case Node.DOCUMENT_TYPE_NODE :
+ case Node.ENTITY_NODE :
+ case Node.ENTITY_REFERENCE_NODE:
+ case Node.NOTATION_NODE :
+ // These node types are ignored!!!
+ break;
+ case Node.CDATA_SECTION_NODE:
+ final String cdata = node.getNodeValue();
+ if (_lex != null) {
+ _lex.startCDATA();
+ _sax.characters(cdata.toCharArray(), 0, cdata.length());
+ _lex.endCDATA();
+ }
+ else {
+ // in the case where there is no lex handler, we still
+ // want the text of the cdate to make its way through.
+ _sax.characters(cdata.toCharArray(), 0, cdata.length());
+ }
+ break;
+
+ case Node.COMMENT_NODE: // should be handled!!!
+ if (_lex != null) {
+ final String value = node.getNodeValue();
+ _lex.comment(value.toCharArray(), 0, value.length());
+ }
+ break;
+ case Node.DOCUMENT_NODE:
+ _sax.setDocumentLocator(this);
+
+ _sax.startDocument();
+ Node next = node.getFirstChild();
+ while (next != null) {
+ parse(next);
+ next = next.getNextSibling();
+ }
+ _sax.endDocument();
+ break;
+
+ case Node.ELEMENT_NODE:
+ String prefix;
+ Vector pushedPrefixes = new Vector();
+ final AttributesImpl attrs = new AttributesImpl();
+ final NamedNodeMap map = node.getAttributes();
+ final int length = map.getLength();
+
+ // Process all namespace declarations
+ for (int i = 0; i < length; i++) {
+ final Node attr = map.item(i);
+ final String qnameAttr = attr.getNodeName();
+
+ // Ignore everything but NS declarations here
+ if (qnameAttr.startsWith(XMLNS_PREFIX)) {
+ final String uriAttr = attr.getNodeValue();
+ final int colon = qnameAttr.lastIndexOf(':');
+ prefix = (colon > 0) ? qnameAttr.substring(colon + 1) : EMPTYSTRING;
+ if (startPrefixMapping(prefix, uriAttr)) {
+ pushedPrefixes.addElement(prefix);
+ }
+ }
+ }
+
+ // Process all other attributes
+ for (int i = 0; i < length; i++) {
+ final Node attr = map.item(i);
+ String qnameAttr = attr.getNodeName();
+
+ // Ignore NS declarations here
+ if (!qnameAttr.startsWith(XMLNS_PREFIX)) {
+ final String uriAttr = attr.getNamespaceURI();
+ final String localNameAttr = getLocalName(attr);
+
+ // Uri may be implicitly declared
+ if (uriAttr != null) {
+ final int colon = qnameAttr.lastIndexOf(':');
+ if (colon > 0) {
+ prefix = qnameAttr.substring(0, colon);
+ }
+ else {
+ // If no prefix for this attr, we need to create
+ // one because we cannot use the default ns
+ prefix = BasisLibrary.generatePrefix();
+ qnameAttr = prefix + ':' + qnameAttr;
+ }
+ if (startPrefixMapping(prefix, uriAttr)) {
+ pushedPrefixes.addElement(prefix);
+ }
+ }
+
+ // Add attribute to list
+ attrs.addAttribute(attr.getNamespaceURI(), getLocalName(attr),
+ qnameAttr, "CDATA", attr.getNodeValue());
+ }
+ }
+
+ // Now process the element itself
+ final String qname = node.getNodeName();
+ final String uri = node.getNamespaceURI();
+ final String localName = getLocalName(node);
+
+ // Uri may be implicitly declared
+ if (uri != null) {
+ final int colon = qname.lastIndexOf(':');
+ prefix = (colon > 0) ? qname.substring(0, colon) : EMPTYSTRING;
+ if (startPrefixMapping(prefix, uri)) {
+ pushedPrefixes.addElement(prefix);
+ }
+ }
+
+ // Generate SAX event to start element
+ if (_saxImpl != null) {
+ _saxImpl.startElement(uri, localName, qname, attrs, node);
+ }
+ else {
+ _sax.startElement(uri, localName, qname, attrs);
+ }
+
+ // Traverse all child nodes of the element (if any)
+ next = node.getFirstChild();
+ while (next != null) {
+ parse(next);
+ next = next.getNextSibling();
+ }
+
+ // Generate SAX event to close element
+ _sax.endElement(uri, localName, qname);
+
+ // Generate endPrefixMapping() for all pushed prefixes
+ final int nPushedPrefixes = pushedPrefixes.size();
+ for (int i = 0; i < nPushedPrefixes; i++) {
+ endPrefixMapping((String) pushedPrefixes.elementAt(i));
+ }
+ break;
+
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ _sax.processingInstruction(node.getNodeName(),
+ node.getNodeValue());
+ break;
+
+ case Node.TEXT_NODE:
+ final String data = node.getNodeValue();
+ _sax.characters(data.toCharArray(), 0, data.length());
+ break;
+ }
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public DTDHandler getDTDHandler() {
+ return null;
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public ErrorHandler getErrorHandler() {
+ return null;
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public boolean getFeature(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException
+ {
+ return false;
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public void setFeature(String name, boolean value) throws
+ SAXNotRecognizedException, SAXNotSupportedException
+ {
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public void parse(String sysId) throws IOException, SAXException {
+ throw new IOException("This method is not yet implemented.");
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public void setDTDHandler(DTDHandler handler) throws NullPointerException {
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public void setEntityResolver(EntityResolver resolver) throws
+ NullPointerException
+ {
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public EntityResolver getEntityResolver() {
+ return null;
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public void setErrorHandler(ErrorHandler handler) throws
+ NullPointerException
+ {
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public void setProperty(String name, Object value) throws
+ SAXNotRecognizedException, SAXNotSupportedException {
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public Object getProperty(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException
+ {
+ return null;
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public int getColumnNumber() {
+ return 0;
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public int getLineNumber() {
+ return 0;
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public String getPublicId() {
+ return null;
+ }
+
+ /**
+ * This class is only used internally so this method should never
+ * be called.
+ */
+ public String getSystemId() {
+ return null;
+ }
+
+ // Debugging
+ private String getNodeTypeFromCode(short code) {
+ String retval = null;
+ switch (code) {
+ case Node.ATTRIBUTE_NODE :
+ retval = "ATTRIBUTE_NODE"; break;
+ case Node.CDATA_SECTION_NODE :
+ retval = "CDATA_SECTION_NODE"; break;
+ case Node.COMMENT_NODE :
+ retval = "COMMENT_NODE"; break;
+ case Node.DOCUMENT_FRAGMENT_NODE :
+ retval = "DOCUMENT_FRAGMENT_NODE"; break;
+ case Node.DOCUMENT_NODE :
+ retval = "DOCUMENT_NODE"; break;
+ case Node.DOCUMENT_TYPE_NODE :
+ retval = "DOCUMENT_TYPE_NODE"; break;
+ case Node.ELEMENT_NODE :
+ retval = "ELEMENT_NODE"; break;
+ case Node.ENTITY_NODE :
+ retval = "ENTITY_NODE"; break;
+ case Node.ENTITY_REFERENCE_NODE :
+ retval = "ENTITY_REFERENCE_NODE"; break;
+ case Node.NOTATION_NODE :
+ retval = "NOTATION_NODE"; break;
+ case Node.PROCESSING_INSTRUCTION_NODE :
+ retval = "PROCESSING_INSTRUCTION_NODE"; break;
+ case Node.TEXT_NODE:
+ retval = "TEXT_NODE"; break;
+ }
+ return retval;
+ }
+}