| /* | ||
| * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved. | ||
| * | ||
| * This software is open source. | ||
| * See the bottom of this file for the licence. | ||
| * | ||
| * $Id: DOMWriter.java,v 1.15 2004/06/28 14:19:33 maartenc Exp $ | ||
| */ | ||
| package org.dom4j.io; | ||
| import java.util.List; | ||
| import org.dom4j.Attribute; | ||
| import org.dom4j.CDATA; | ||
| import org.dom4j.Comment; | ||
| import org.dom4j.Document; | ||
| import org.dom4j.DocumentException; | ||
| import org.dom4j.Element; | ||
| import org.dom4j.Entity; | ||
| import org.dom4j.Namespace; | ||
| import org.dom4j.ProcessingInstruction; | ||
| import org.dom4j.Text; | ||
| import org.dom4j.tree.NamespaceStack; | ||
| /** <p><code>DOMWriter</code> takes a DOM4J tree and outputs | ||
| * it as a W3C DOM object</p> | ||
| * | ||
| * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a> | ||
| * @version $Revision: 1.15 $ | ||
| */ | ||
| public class DOMWriter { | ||
| private static boolean loggedWarning = false; | ||
| private static final String[] DEFAULT_DOM_DOCUMENT_CLASSES = { | ||
| "org.apache.xerces.dom.DocumentImpl", // Xerces | ||
| "gnu.xml.dom.DomDocument", // GNU JAXP | ||
| "org.apache.crimson.tree.XmlDocument", // Crimson | ||
| "com.sun.xml.tree.XmlDocument", // Sun's Project X | ||
| "oracle.xml.parser.v2.XMLDocument", // Oracle V2 | ||
| "oracle.xml.parser.XMLDocument", // Oracle V1 | ||
| "org.dom4j.dom.DOMDocument" // Internal DOM implementation | ||
| }; | ||
| // the Class used to create new DOM Document instances | ||
| private Class domDocumentClass; | ||
| /** stack of <code>Namespace</code> objects */ | ||
| 2x | private NamespaceStack namespaceStack = new NamespaceStack(); | |
| 2x | public DOMWriter() { | |
| 2x | } | |
| 0x | public DOMWriter(Class domDocumentClass) { | |
| 0x | this.domDocumentClass = domDocumentClass; | |
| 0x | } | |
| public Class getDomDocumentClass() throws DocumentException { | ||
| 0x | Class result = domDocumentClass; | |
| 0/2 0x | if ( result == null ) { | |
| // lets try and find one in the classpath | ||
| 0x | int size = DEFAULT_DOM_DOCUMENT_CLASSES.length; | |
| 0/2 0x | for ( int i = 0; i < size; i++ ) { | |
| try { | ||
| 0x | String name = DEFAULT_DOM_DOCUMENT_CLASSES[i]; | |
| 0x | result = Class.forName( | |
| name, | ||
| true, | ||
| DOMWriter.class.getClassLoader() | ||
| ); | ||
| 0/2 0x | if ( result != null ) { | |
| 0x | break; | |
| } | ||
| } | ||
| catch (Exception e) { | ||
| // could not load class correctly | ||
| // lets carry on to the next one | ||
| 0x | } | |
| } | ||
| } | ||
| 0x | return result; | |
| } | ||
| /** Sets the DOM {@link org.w3c.dom.Document} implementation | ||
| * class used by the writer when creating DOM documents. | ||
| * | ||
| * @param domDocumentClass is the Class implementing | ||
| * the {@link org.w3c.dom.Document} interface | ||
| */ | ||
| public void setDomDocumentClass(Class domDocumentClass) { | ||
| 0x | this.domDocumentClass = domDocumentClass; | |
| 0x | } | |
| /** Sets the DOM {@link org.w3c.dom.Document} implementation | ||
| * class name used by the writer when creating DOM documents. | ||
| * | ||
| * @param className is the name of the Class implementing | ||
| * the {@link org.w3c.dom.Document} interface | ||
| * @throws DocumentException if the class could not be loaded | ||
| */ | ||
| public void setDomDocumentClassName(String className) throws DocumentException { | ||
| try { | ||
| 0x | this.domDocumentClass = Class.forName( | |
| className, | ||
| true, | ||
| DOMWriter.class.getClassLoader() | ||
| ); | ||
| } | ||
| catch (Exception e) { | ||
| 0x | throw new DocumentException( | |
| "Could not load the DOM Document class: " + className, e | ||
| ); | ||
| 0x | } | |
| 0x | } | |
| public org.w3c.dom.Document write(Document document) throws DocumentException { | ||
| 1/2 2x | if ( document instanceof org.w3c.dom.Document ) { | |
| 2x | return (org.w3c.dom.Document) document; | |
| } | ||
| 0x | resetNamespaceStack(); | |
| 0x | org.w3c.dom.Document domDocument = createDomDocument(document); | |
| 0x | appendDOMTree(domDocument, domDocument, document.content()); | |
| 0x | namespaceStack.clear(); | |
| 0x | return domDocument; | |
| } | ||
| public org.w3c.dom.Document write( | ||
| Document document, | ||
| org.w3c.dom.DOMImplementation domImplementation | ||
| ) throws DocumentException { | ||
| 0/2 0x | if ( document instanceof org.w3c.dom.Document ) { | |
| 0x | return (org.w3c.dom.Document) document; | |
| } | ||
| 0x | resetNamespaceStack(); | |
| 0x | org.w3c.dom.Document domDocument = createDomDocument(document, domImplementation); | |
| 0x | appendDOMTree(domDocument, domDocument, document.content()); | |
| 0x | namespaceStack.clear(); | |
| 0x | return domDocument; | |
| } | ||
| protected void appendDOMTree( | ||
| org.w3c.dom.Document domDocument, | ||
| org.w3c.dom.Node domCurrent, | ||
| List content | ||
| ) { | ||
| 0x | int size = content.size(); | |
| 0/2 0x | for ( int i = 0; i < size; i++ ) { | |
| 0x | Object object = content.get(i); | |
| 0/2 0x | if (object instanceof Element) { | |
| 0x | appendDOMTree( domDocument, domCurrent, (Element) object); | |
| } | ||
| 0/2 0x | else if ( object instanceof String ) { | |
| 0x | appendDOMTree( domDocument, domCurrent, (String) object ); | |
| } | ||
| 0/2 0x | else if ( object instanceof Text ) { | |
| 0x | Text text = (Text) object; | |
| 0x | appendDOMTree( domDocument, domCurrent, text.getText() ); | |
| } | ||
| 0/2 0x | else if ( object instanceof CDATA ) { | |
| 0x | appendDOMTree( domDocument, domCurrent, (CDATA) object ); | |
| } | ||
| 0/2 0x | else if ( object instanceof Comment ) { | |
| 0x | appendDOMTree( domDocument, domCurrent, (Comment) object ); | |
| } | ||
| 0/2 0x | else if ( object instanceof Entity ) { | |
| 0x | appendDOMTree( domDocument, domCurrent, (Entity) object ); | |
| } | ||
| 0/2 0x | else if ( object instanceof ProcessingInstruction ) { | |
| 0x | appendDOMTree( domDocument, domCurrent, (ProcessingInstruction) object ); | |
| } | ||
| } | ||
| 0x | } | |
| protected void appendDOMTree( | ||
| org.w3c.dom.Document domDocument, | ||
| org.w3c.dom.Node domCurrent, | ||
| Element element | ||
| ) { | ||
| 0x | String elUri = element.getNamespaceURI(); | |
| 0x | String elName = element.getQualifiedName(); | |
| 0x | org.w3c.dom.Element domElement = domDocument.createElementNS(elUri, elName); | |
| 0x | int stackSize = namespaceStack.size(); | |
| // add the namespace of the element first | ||
| 0x | Namespace elementNamespace = element.getNamespace(); | |
| 0/2 0x | if (isNamespaceDeclaration(elementNamespace)) { | |
| 0x | namespaceStack.push(elementNamespace); | |
| 0x | writeNamespace(domElement, elementNamespace); | |
| } | ||
| // add the additional declared namespaces | ||
| 0x | List declaredNamespaces = element.declaredNamespaces(); | |
| 0/2 0x | for ( int i = 0, size = declaredNamespaces.size(); i < size ; i++ ) { | |
| 0x | Namespace namespace = (Namespace) declaredNamespaces.get(i); | |
| 0/2 0x | if ( isNamespaceDeclaration( namespace ) ) { | |
| 0x | namespaceStack.push( namespace ); | |
| 0x | writeNamespace( domElement, namespace ); | |
| } | ||
| } | ||
| // add the attributes | ||
| 0/2 0x | for ( int i = 0, size = element.attributeCount(); i < size ; i++ ) { | |
| 0x | Attribute attribute = (Attribute) element.attribute(i); | |
| 0x | String attUri = attribute.getNamespaceURI(); | |
| 0x | String attName = attribute.getQualifiedName(); | |
| 0x | String value = attribute.getValue(); | |
| 0x | domElement.setAttributeNS(attUri, attName, value); | |
| } | ||
| // add content | ||
| 0x | appendDOMTree( domDocument, domElement, element.content() ); | |
| 0x | domCurrent.appendChild( domElement ); | |
| 0/2 0x | while ( namespaceStack.size() > stackSize ) { | |
| 0x | namespaceStack.pop(); | |
| } | ||
| 0x | } | |
| protected void appendDOMTree( | ||
| org.w3c.dom.Document domDocument, | ||
| org.w3c.dom.Node domCurrent, | ||
| CDATA cdata | ||
| ) { | ||
| 0x | org.w3c.dom.CDATASection domCDATA = | |
| domDocument.createCDATASection(cdata.getText()); | ||
| 0x | domCurrent.appendChild(domCDATA); | |
| 0x | } | |
| protected void appendDOMTree( | ||
| org.w3c.dom.Document domDocument, | ||
| org.w3c.dom.Node domCurrent, | ||
| Comment comment | ||
| ) { | ||
| 0x | org.w3c.dom.Comment domComment = | |
| domDocument.createComment(comment.getText()); | ||
| 0x | domCurrent.appendChild(domComment); | |
| 0x | } | |
| protected void appendDOMTree( | ||
| org.w3c.dom.Document domDocument, | ||
| org.w3c.dom.Node domCurrent, | ||
| String text | ||
| ) { | ||
| 0x | org.w3c.dom.Text domText = domDocument.createTextNode(text); | |
| 0x | domCurrent.appendChild(domText); | |
| 0x | } | |
| protected void appendDOMTree( | ||
| org.w3c.dom.Document domDocument, | ||
| org.w3c.dom.Node domCurrent, | ||
| Entity entity | ||
| ) { | ||
| 0x | org.w3c.dom.EntityReference domEntity = | |
| domDocument.createEntityReference(entity.getName()); | ||
| 0x | domCurrent.appendChild(domEntity); | |
| 0x | } | |
| protected void appendDOMTree( | ||
| org.w3c.dom.Document domDocument, | ||
| org.w3c.dom.Node domCurrent, | ||
| ProcessingInstruction pi | ||
| ) { | ||
| 0x | org.w3c.dom.ProcessingInstruction domPI = | |
| domDocument.createProcessingInstruction(pi.getTarget(), pi.getText()); | ||
| 0x | domCurrent.appendChild(domPI); | |
| 0x | } | |
| protected void writeNamespace( | ||
| org.w3c.dom.Element domElement, | ||
| Namespace namespace | ||
| ) { | ||
| 0x | String attributeName = attributeNameForNamespace(namespace); | |
| //domElement.setAttributeNS("", attributeName, namespace.getURI()); | ||
| 0x | domElement.setAttribute(attributeName, namespace.getURI()); | |
| 0x | } | |
| protected String attributeNameForNamespace(Namespace namespace) { | ||
| 0x | String xmlns = "xmlns"; | |
| 0x | String prefix = namespace.getPrefix(); | |
| 0/2 0x | if ( prefix.length() > 0 ) { | |
| 0x | return xmlns + ":" + prefix; | |
| } | ||
| 0x | return xmlns; | |
| } | ||
| protected org.w3c.dom.Document createDomDocument( | ||
| Document document | ||
| ) throws DocumentException { | ||
| 0x | org.w3c.dom.Document result = null; | |
| // use the given domDocumentClass (if not null) | ||
| 0/2 0x | if (domDocumentClass != null) { | |
| try { | ||
| 0x | result = (org.w3c.dom.Document) domDocumentClass.newInstance(); | |
| } | ||
| catch (Exception e) { | ||
| 0x | throw new DocumentException( | |
| "Could not instantiate an instance of DOM Document with class: " | ||
| + domDocumentClass.getName(), e | ||
| ); | ||
| 0x | } | |
| } else { | ||
| // lets try JAXP first before using the hardcoded default parsers | ||
| 0x | result = createDomDocumentViaJAXP(); | |
| 0/2 0x | if ( result == null ) { | |
| 0x | Class theClass = getDomDocumentClass(); | |
| try { | ||
| 0x | result = (org.w3c.dom.Document) theClass.newInstance(); | |
| } | ||
| catch (Exception e) { | ||
| 0x | throw new DocumentException( | |
| "Could not instantiate an instance of DOM Document with class: " | ||
| + theClass.getName(), e | ||
| ); | ||
| 0x | } | |
| } | ||
| } | ||
| 0x | return result; | |
| } | ||
| protected org.w3c.dom.Document createDomDocumentViaJAXP() throws DocumentException { | ||
| try { | ||
| 0x | return JAXPHelper.createDocument( false, true ); | |
| } | ||
| catch (Throwable e) { | ||
| 0/2 0x | if ( ! loggedWarning ) { | |
| 0x | loggedWarning = true; | |
| 0/2 0x | if ( SAXHelper.isVerboseErrorReporting() ) { | |
| // log all exceptions as warnings and carry | ||
| // on as we have a default SAX parser we can use | ||
| 0x | System.out.println( | |
| "Warning: Caught exception attempting to use JAXP to " | ||
| + "create a W3C DOM document" | ||
| ); | ||
| 0x | System.out.println( "Warning: Exception was: " + e ); | |
| 0x | e.printStackTrace(); | |
| } | ||
| else { | ||
| 0x | System.out.println( | |
| "Warning: Error occurred using JAXP to create a DOM document." | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| 0x | return null; | |
| } | ||
| protected org.w3c.dom.Document createDomDocument( | ||
| Document document, | ||
| org.w3c.dom.DOMImplementation domImplementation | ||
| ) throws DocumentException { | ||
| 0x | String namespaceURI = null; | |
| 0x | String qualifiedName = null; | |
| 0x | org.w3c.dom.DocumentType docType = null; | |
| 0x | return domImplementation.createDocument( | |
| namespaceURI, qualifiedName, docType | ||
| ); | ||
| } | ||
| protected boolean isNamespaceDeclaration( Namespace ns ) { | ||
| 0/6 0x | if (ns != null && ns != Namespace.NO_NAMESPACE && ns != Namespace.XML_NAMESPACE) { | |
| 0x | String uri = ns.getURI(); | |
| 0/4 0x | if ( uri != null && uri.length() > 0 ) { | |
| 0/2 0x | if ( ! namespaceStack.contains( ns ) ) { | |
| 0x | return true; | |
| } | ||
| } | ||
| } | ||
| 0x | return false; | |
| } | ||
| protected void resetNamespaceStack() { | ||
| 0x | namespaceStack.clear(); | |
| 0x | namespaceStack.push( Namespace.XML_NAMESPACE ); | |
| 0x | } | |
| } | ||
| /* | ||
| * Redistribution and use of this software and associated documentation | ||
| * ("Software"), with or without modification, are permitted provided | ||
| * that the following conditions are met: | ||
| * | ||
| * 1. Redistributions of source code must retain copyright | ||
| * statements and notices. Redistributions must also contain a | ||
| * copy of this document. | ||
| * | ||
| * 2. 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. | ||
| * | ||
| * 3. The name "DOM4J" must not be used to endorse or promote | ||
| * products derived from this Software without prior written | ||
| * permission of MetaStuff, Ltd. For written permission, | ||
| * please contact dom4j-info@metastuff.com. | ||
| * | ||
| * 4. Products derived from this Software may not be called "DOM4J" | ||
| * nor may "DOM4J" appear in their names without prior written | ||
| * permission of MetaStuff, Ltd. DOM4J is a registered | ||
| * trademark of MetaStuff, Ltd. | ||
| * | ||
| * 5. Due credit should be given to the DOM4J Project - | ||
| * http://www.dom4j.org | ||
| * | ||
| * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS | ||
| * ``AS IS'' AND ANY EXPRESSED 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 | ||
| * METASTUFF, LTD. OR ITS 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. | ||
| * | ||
| * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved. | ||
| * | ||
| * $Id: DOMWriter.java,v 1.15 2004/06/28 14:19:33 maartenc Exp $ | ||
| */ |