Project dom4j 1.5.2 [5/2/05 10:13 PM]
 
Coverage - org/dom4j/io/DOMReader.java
  /*
   * 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 $
   */