| /* |
| * reserved comment block |
| * DO NOT REMOVE OR ALTER! |
| */ |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| package com.sun.org.apache.xalan.internal.xsltc.trax; |
| |
| import java.io.IOException; |
| |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.Document; |
| import com.sun.org.apache.xml.internal.serializer.SerializationHandler; |
| 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.ext.Locator2; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXNotRecognizedException; |
| import org.xml.sax.SAXNotSupportedException; |
| import org.xml.sax.XMLReader; |
| import com.sun.org.apache.xml.internal.serializer.NamespaceMappings; |
| |
| /** |
| * @author Santiago Pericas-Geertsen |
| * @author Sunitha Reddy |
| */ |
| public class DOM2TO implements XMLReader, Locator2 { |
| |
| private final static String EMPTYSTRING = ""; |
| private static final String XMLNS_PREFIX = "xmlns"; |
| |
| /** |
| * A reference to the DOM to be traversed. |
| */ |
| private Node _dom; |
| |
| /** |
| * A reference to the output handler receiving the events. |
| */ |
| private SerializationHandler _handler; |
| |
| |
| private String xmlVersion = null; |
| |
| private String xmlEncoding = null; |
| |
| |
| public DOM2TO(Node root, SerializationHandler handler) { |
| _dom = root; |
| _handler = handler; |
| } |
| |
| public ContentHandler getContentHandler() { |
| return null; |
| } |
| |
| public void setContentHandler(ContentHandler handler) { |
| // Empty |
| } |
| |
| 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) { |
| _handler.startDocument(); |
| parse(_dom); |
| _handler.endDocument(); |
| } |
| else { |
| parse(_dom); |
| } |
| } |
| } |
| |
| /** |
| * Traverse the DOM and generate TO events for a handler. Notice that |
| * we need to handle implicit namespace declarations too. |
| */ |
| private void parse(Node node) |
| throws IOException, SAXException |
| { |
| if (node == null) return; |
| |
| switch (node.getNodeType()) { |
| case Node.ATTRIBUTE_NODE: // handled by ELEMENT_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: |
| _handler.startCDATA(); |
| _handler.characters(node.getNodeValue()); |
| _handler.endCDATA(); |
| break; |
| |
| case Node.COMMENT_NODE: // should be handled!!! |
| _handler.comment(node.getNodeValue()); |
| break; |
| |
| case Node.DOCUMENT_NODE: |
| setDocumentInfo((Document)node); |
| _handler.setDocumentLocator(this); |
| _handler.startDocument(); |
| Node next = node.getFirstChild(); |
| while (next != null) { |
| parse(next); |
| next = next.getNextSibling(); |
| } |
| _handler.endDocument(); |
| break; |
| |
| case Node.DOCUMENT_FRAGMENT_NODE: |
| next = node.getFirstChild(); |
| while (next != null) { |
| parse(next); |
| next = next.getNextSibling(); |
| } |
| break; |
| |
| case Node.ELEMENT_NODE: |
| // Generate SAX event to start element |
| final String qname = node.getNodeName(); |
| _handler.startElement(null, null, qname); |
| |
| int colon; |
| String prefix; |
| final NamedNodeMap map = node.getAttributes(); |
| final int length = map.getLength(); |
| |
| // Process all namespace attributes first |
| for (int i = 0; i < length; i++) { |
| final Node attr = map.item(i); |
| final String qnameAttr = attr.getNodeName(); |
| |
| // Is this a namespace declaration? |
| if (qnameAttr.startsWith(XMLNS_PREFIX)) { |
| final String uriAttr = attr.getNodeValue(); |
| colon = qnameAttr.lastIndexOf(':'); |
| prefix = (colon > 0) ? qnameAttr.substring(colon + 1) |
| : EMPTYSTRING; |
| _handler.namespaceAfterStartElement(prefix, uriAttr); |
| } |
| } |
| |
| // Process all non-namespace attributes next |
| NamespaceMappings nm = new NamespaceMappings(); |
| for (int i = 0; i < length; i++) { |
| final Node attr = map.item(i); |
| final String qnameAttr = attr.getNodeName(); |
| |
| // Is this a regular attribute? |
| if (!qnameAttr.startsWith(XMLNS_PREFIX)) { |
| final String uriAttr = attr.getNamespaceURI(); |
| // Uri may be implicitly declared |
| if (uriAttr != null && !uriAttr.equals(EMPTYSTRING) ) { |
| colon = qnameAttr.lastIndexOf(':'); |
| |
| // Fix for bug 26319 |
| // For attributes not given an prefix explictly |
| // but having a namespace uri we need |
| // to explicitly generate the prefix |
| String newPrefix = nm.lookupPrefix(uriAttr); |
| if (newPrefix == null) |
| newPrefix = nm.generateNextPrefix(); |
| prefix = (colon > 0) ? qnameAttr.substring(0, colon) |
| : newPrefix; |
| _handler.namespaceAfterStartElement(prefix, uriAttr); |
| _handler.addAttribute((prefix + ":" + qnameAttr), |
| attr.getNodeValue()); |
| } else { |
| _handler.addAttribute(qnameAttr, attr.getNodeValue()); |
| } |
| } |
| } |
| |
| // Now element namespace and children |
| final String uri = node.getNamespaceURI(); |
| final String localName = node.getLocalName(); |
| |
| // Uri may be implicitly declared |
| if (uri != null) { |
| colon = qname.lastIndexOf(':'); |
| prefix = (colon > 0) ? qname.substring(0, colon) : EMPTYSTRING; |
| _handler.namespaceAfterStartElement(prefix, uri); |
| }else { |
| // Fix for bug 26319 |
| // If an element foo is created using |
| // createElementNS(null,locName) |
| // then the element should be serialized |
| // <foo xmlns=" "/> |
| if (uri == null && localName != null) { |
| prefix = EMPTYSTRING; |
| _handler.namespaceAfterStartElement(prefix, EMPTYSTRING); |
| } |
| } |
| |
| // 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 |
| _handler.endElement(qname); |
| break; |
| |
| case Node.PROCESSING_INSTRUCTION_NODE: |
| _handler.processingInstruction(node.getNodeName(), |
| node.getNodeValue()); |
| break; |
| |
| case Node.TEXT_NODE: |
| _handler.characters(node.getNodeValue()); |
| 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; |
| } |
| |
| |
| private void setDocumentInfo(Document document) { |
| if (!document.getXmlStandalone()) |
| _handler.setStandalone(Boolean.toString(document.getXmlStandalone())); |
| setXMLVersion(document.getXmlVersion()); |
| setEncoding(document.getXmlEncoding()); |
| } |
| |
| public String getXMLVersion() { |
| return xmlVersion; |
| } |
| |
| private void setXMLVersion(String version) { |
| if (version != null) { |
| xmlVersion = version; |
| _handler.setVersion(xmlVersion); |
| } |
| } |
| |
| public String getEncoding() { |
| return xmlEncoding; |
| } |
| |
| private void setEncoding(String encoding) { |
| if (encoding != null) { |
| xmlEncoding = encoding; |
| _handler.setEncoding(encoding); |
| } |
| } |
| |
| // 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; |
| } |
| } |