| /* | ||
| * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved. | ||
| * | ||
| * This software is open source. | ||
| * See the bottom of this file for the licence. | ||
| * | ||
| * $Id: DOMReader.java,v 1.15 2004/06/25 08:03:36 maartenc Exp $ | ||
| */ | ||
| package org.dom4j.io; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import org.dom4j.Branch; | ||
| import org.dom4j.Document; | ||
| import org.dom4j.DocumentFactory; | ||
| import org.dom4j.Element; | ||
| import org.dom4j.Namespace; | ||
| import org.dom4j.QName; | ||
| import org.dom4j.tree.NamespaceStack; | ||
| /** <p><code>DOMReader</code> navigates a W3C DOM tree and creates | ||
| * a DOM4J tree from it.</p> | ||
| * | ||
| * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> | ||
| * @version $Revision: 1.15 $ | ||
| */ | ||
| public class DOMReader { | ||
| /** <code>DocumentFactory</code> used to create new document objects */ | ||
| private DocumentFactory factory; | ||
| /** stack of <code>Namespace</code> and <code>QName</code> objects */ | ||
| private NamespaceStack namespaceStack; | ||
| 2x | public DOMReader() { | |
| 2x | this.factory = DocumentFactory.getInstance(); | |
| 2x | this.namespaceStack = new NamespaceStack(factory); | |
| 2x | } | |
| 0x | public DOMReader(DocumentFactory factory) { | |
| 0x | this.factory = factory; | |
| 0x | this.namespaceStack = new NamespaceStack(factory); | |
| 0x | } | |
| /** @return the <code>DocumentFactory</code> used to create document objects | ||
| */ | ||
| public DocumentFactory getDocumentFactory() { | ||
| 2x | return factory; | |
| } | ||
| /** <p>This sets the <code>DocumentFactory</code> used to create new documents. | ||
| * This method allows the building of custom DOM4J tree objects to be implemented | ||
| * easily using a custom derivation of {@link DocumentFactory}</p> | ||
| * | ||
| * @param factory <code>DocumentFactory</code> used to create DOM4J objects | ||
| */ | ||
| public void setDocumentFactory(DocumentFactory factory) { | ||
| 0x | this.factory = factory; | |
| 0x | this.namespaceStack.setDocumentFactory(factory); | |
| 0x | } | |
| public Document read(org.w3c.dom.Document domDocument) { | ||
| 1/2 2x | if ( domDocument instanceof Document ) { | |
| 0x | return (Document) domDocument; | |
| } | ||
| 2x | Document document = createDocument(); | |
| 2x | clearNamespaceStack(); | |
| 2x | org.w3c.dom.NodeList nodeList = domDocument.getChildNodes(); | |
| 2/2 4x | for ( int i = 0, size = nodeList.getLength(); i < size; i++ ) { | |
| 2x | readTree( nodeList.item(i), document ); | |
| } | ||
| 2x | return document; | |
| } | ||
| // Implementation methods | ||
| protected void readTree(org.w3c.dom.Node node, Branch current) { | ||
| 22x | Element element = null; | |
| 22x | Document document = null; | |
| 2/2 22x | if ( current instanceof Element ) { | |
| 20x | element = (Element) current; | |
| } | ||
| else { | ||
| 2x | document = (Document) current; | |
| } | ||
| 22x | switch (node.getNodeType()) { | |
| case org.w3c.dom.Node.ELEMENT_NODE: | ||
| 10x | readElement(node, current); | |
| 10x | break; | |
| case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE: | ||
| 0/2 0x | if ( current instanceof Element ) { | |
| 0x | ((Element) current).addProcessingInstruction( | |
| node.getNodeName(), node.getNodeValue() | ||
| ); | ||
| } | ||
| else { | ||
| 0x | ((Document) current).addProcessingInstruction( | |
| node.getNodeName(), node.getNodeValue() | ||
| ); | ||
| } | ||
| 0x | break; | |
| case org.w3c.dom.Node.COMMENT_NODE: | ||
| 0/2 0x | if ( current instanceof Element ) { | |
| 0x | ((Element) current).addComment( node.getNodeValue() ); | |
| } | ||
| else { | ||
| 0x | ((Document) current).addComment( node.getNodeValue() ); | |
| } | ||
| 0x | break; | |
| case org.w3c.dom.Node.DOCUMENT_TYPE_NODE: | ||
| 0x | org.w3c.dom.DocumentType domDocType | |
| = (org.w3c.dom.DocumentType) node; | ||
| 0x | document.addDocType( | |
| domDocType.getName(), | ||
| domDocType.getPublicId(), | ||
| domDocType.getSystemId() | ||
| ); | ||
| 0x | break; | |
| case org.w3c.dom.Node.TEXT_NODE: | ||
| 12x | element.addText( node.getNodeValue() ); | |
| 12x | break; | |
| case org.w3c.dom.Node.CDATA_SECTION_NODE: | ||
| 0x | element.addCDATA( node.getNodeValue() ); | |
| 0x | break; | |
| case org.w3c.dom.Node.ENTITY_REFERENCE_NODE: { | ||
| // is there a better way to get the value of an entity? | ||
| 0x | org.w3c.dom.Node firstChild = node.getFirstChild(); | |
| 0/2 0x | if ( firstChild != null ) { | |
| 0x | element.addEntity( | |
| node.getNodeName(), | ||
| firstChild.getNodeValue() | ||
| ); | ||
| } | ||
| else { | ||
| 0x | element.addEntity( node.getNodeName(), "" ); | |
| } | ||
| } | ||
| 0x | break; | |
| case org.w3c.dom.Node.ENTITY_NODE: | ||
| 0x | element.addEntity( | |
| node.getNodeName(), | ||
| node.getNodeValue() | ||
| ); | ||
| 0x | break; | |
| default: | ||
| 0x | System.out.println( "WARNING: Unknown DOM node type: " + node.getNodeType() ); | |
| } | ||
| 22x | } | |
| protected void readElement(org.w3c.dom.Node node, Branch current) { | ||
| 10x | int previouslyDeclaredNamespaces = namespaceStack.size(); | |
| 10x | String namespaceUri = node.getNamespaceURI(); | |
| 10x | String elementPrefix = node.getPrefix(); | |
| 1/2 10x | if (elementPrefix == null) { | |
| 10x | elementPrefix = ""; | |
| } | ||
| 10x | org.w3c.dom.NamedNodeMap attributeList = node.getAttributes(); | |
| 2/4 10x | if (( attributeList != null ) && ( namespaceUri == null )) { | |
| // test if we have an "xmlns" attribute | ||
| 10x | org.w3c.dom.Node attribute = attributeList.getNamedItem( "xmlns" ); | |
| 2/2 10x | if ( attribute != null ) { | |
| 2x | namespaceUri = attribute.getNodeValue(); | |
| 2x | elementPrefix = ""; | |
| } | ||
| } | ||
| 10x | QName qName = namespaceStack.getQName( namespaceUri, node.getLocalName(), node.getNodeName() ); | |
| 10x | Element element = current.addElement(qName); | |
| 1/2 10x | if ( attributeList != null ) { | |
| 10x | int size = attributeList.getLength(); | |
| 10x | List attributes = new ArrayList(size); | |
| 2/2 26x | for ( int i = 0; i < size; i++ ) { | |
| 16x | org.w3c.dom.Node attribute = attributeList.item(i); | |
| // Define all namespaces first then process attributes later | ||
| 16x | String name = attribute.getNodeName(); | |
| 2/2 16x | if (name.startsWith("xmlns")) { | |
| 4x | String prefix = getPrefix(name); | |
| 4x | String uri = attribute.getNodeValue(); | |
| // if (!uri.equals(namespaceUri) || !prefix.equals(elementPrefix)) { | ||
| 4x | Namespace namespace = namespaceStack.addNamespace( prefix, uri ); | |
| 4x | element.add( namespace ); | |
| // } | ||
| } | ||
| else { | ||
| 12x | attributes.add( attribute ); | |
| } | ||
| } | ||
| // now add the attributes, the namespaces should be available | ||
| 10x | size = attributes.size(); | |
| 2/2 22x | for ( int i = 0; i < size; i++ ) { | |
| 12x | org.w3c.dom.Node attribute = (org.w3c.dom.Node) attributes.get(i); | |
| 12x | QName attributeQName = namespaceStack.getQName( | |
| attribute.getNamespaceURI(), | ||
| attribute.getLocalName(), | ||
| attribute.getNodeName() | ||
| ); | ||
| 12x | element.addAttribute( attributeQName, attribute.getNodeValue() ); | |
| } | ||
| } | ||
| // Recurse on child nodes | ||
| 10x | org.w3c.dom.NodeList children = node.getChildNodes(); | |
| 2/2 30x | for ( int i = 0, size = children.getLength(); i < size; i++ ) { | |
| 20x | org.w3c.dom.Node child = children.item(i); | |
| 20x | readTree( child, element ); | |
| } | ||
| // pop namespaces from the stack | ||
| 2/2 14x | while (namespaceStack.size() > previouslyDeclaredNamespaces) { | |
| 4x | namespaceStack.pop(); | |
| } | ||
| 10x | } | |
| protected Namespace getNamespace(String prefix, String uri) { | ||
| 0x | return getDocumentFactory().createNamespace(prefix, uri); | |
| } | ||
| protected Document createDocument() { | ||
| 2x | return getDocumentFactory().createDocument(); | |
| } | ||
| protected void clearNamespaceStack() { | ||
| 2x | namespaceStack.clear(); | |
| 1/2 2x | if ( ! namespaceStack.contains( Namespace.XML_NAMESPACE ) ) { | |
| 2x | namespaceStack.push( Namespace.XML_NAMESPACE ); | |
| } | ||
| 2x | } | |
| private String getPrefix(String xmlnsDecl) { | ||
| 4x | int index = xmlnsDecl.indexOf(':', 5); | |
| 2/2 4x | if (index != -1) { | |
| 2x | return xmlnsDecl.substring(index + 1); | |
| } else { | ||
| 2x | return ""; | |
| } | ||
| } | ||
| } | ||
| /* | ||
| * 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: DOMReader.java,v 1.15 2004/06/25 08:03:36 maartenc Exp $ | ||
| */ |