mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1556 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1556 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* DomDocument.java --
 | |
|    Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package gnu.xml.dom;
 | |
| 
 | |
| import java.util.Iterator;
 | |
| import javax.xml.XMLConstants;
 | |
| 
 | |
| import org.w3c.dom.Attr;
 | |
| import org.w3c.dom.CDATASection;
 | |
| import org.w3c.dom.Comment;
 | |
| import org.w3c.dom.Document;
 | |
| import org.w3c.dom.DocumentFragment;
 | |
| import org.w3c.dom.DocumentType;
 | |
| import org.w3c.dom.DOMConfiguration;
 | |
| import org.w3c.dom.DOMImplementation;
 | |
| import org.w3c.dom.DOMException;
 | |
| import org.w3c.dom.Element;
 | |
| import org.w3c.dom.Entity;
 | |
| import org.w3c.dom.EntityReference;
 | |
| import org.w3c.dom.NamedNodeMap;
 | |
| import org.w3c.dom.Node;
 | |
| import org.w3c.dom.Notation;
 | |
| import org.w3c.dom.ProcessingInstruction;
 | |
| import org.w3c.dom.Text;
 | |
| import org.w3c.dom.UserDataHandler;
 | |
| import org.w3c.dom.traversal.DocumentTraversal;
 | |
| import org.w3c.dom.traversal.NodeFilter;
 | |
| import org.w3c.dom.traversal.NodeIterator;
 | |
| import org.w3c.dom.traversal.TreeWalker;
 | |
| import org.w3c.dom.xpath.XPathEvaluator;
 | |
| import org.w3c.dom.xpath.XPathException;
 | |
| import org.w3c.dom.xpath.XPathExpression;
 | |
| import org.w3c.dom.xpath.XPathNSResolver;
 | |
| 
 | |
| /**
 | |
|  * <p> "Document" and "DocumentTraversal" implementation.
 | |
|  *
 | |
|  * <p> Note that when this checks names for legality, it uses an
 | |
|  * approximation of the XML rules, not the real ones.  Specifically,
 | |
|  * it uses Unicode rules, with sufficient tweaks to pass a majority
 | |
|  * of basic XML conformance tests.  (The huge XML character tables are
 | |
|  * hairy to implement.)
 | |
|  *
 | |
|  * @author David Brownell
 | |
|  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 | |
|  */
 | |
| public class DomDocument
 | |
|   extends DomNode
 | |
|   implements Document, DocumentTraversal, XPathEvaluator
 | |
| {
 | |
| 
 | |
|   private final DOMImplementation implementation;
 | |
|   private boolean checkingCharacters = true;
 | |
|   boolean checkingWellformedness = true;
 | |
|   private boolean defaultAttributes = true;
 | |
| 
 | |
|   boolean building; // if true, skip mutation events in the tree
 | |
| 
 | |
|   DomDocumentConfiguration config;
 | |
| 
 | |
|   String inputEncoding;
 | |
|   String encoding;
 | |
|   String version = "1.0";
 | |
|   boolean standalone;
 | |
|   String systemId;
 | |
| 
 | |
|   /**
 | |
|    * Constructs a Document node, associating it with an instance
 | |
|    * of the DomImpl class.
 | |
|    *
 | |
|    * <p> Note that this constructor disables character checking.
 | |
|    * It is normally used when connecting a DOM to an XML parser,
 | |
|    * and duplicating such checks is undesirable.  When used for
 | |
|    * purposes other than connecting to a parser, you should
 | |
|    * re-enable that checking.
 | |
|    *
 | |
|    * @see #setCheckingCharacters
 | |
|    */
 | |
|   public DomDocument()
 | |
|   {
 | |
|     this(new DomImpl());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Constructs a Document node, associating it with the specified
 | |
|    * implementation.  This should only be used in conjunction with
 | |
|    * a specialized implementation; it will normally be called by
 | |
|    * that implementation.
 | |
|    *
 | |
|    * @see DomImpl
 | |
|    * @see #setCheckingCharacters
 | |
|    */
 | |
|   protected DomDocument(DOMImplementation impl)
 | |
|   {
 | |
|     super(DOCUMENT_NODE, null);
 | |
|     implementation = impl;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the <code>building</code> flag.
 | |
|    * Mutation events in the document are not reported.
 | |
|    */
 | |
|   public void setBuilding(boolean flag)
 | |
|   {
 | |
|     building = flag;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets whether to check for document well-formedness.
 | |
|    * If true, an exception will be raised if a second doctype or root
 | |
|    * element node is added to the document.
 | |
|    */
 | |
|   public void setCheckWellformedness(boolean flag)
 | |
|   {
 | |
|     checkingWellformedness = flag;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets whether to check for document characters.
 | |
|    */
 | |
|   public void setCheckingCharacters(boolean flag)
 | |
|   {
 | |
|     checkingCharacters = flag;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets whether to default attributes for new elements.
 | |
|    */
 | |
|   public void setDefaultAttributes(boolean flag)
 | |
|   {
 | |
|     defaultAttributes = flag;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns the constant "#document".
 | |
|    */
 | |
|   final public String getNodeName()
 | |
|   {
 | |
|     return "#document";
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns the document's root element, or null.
 | |
|    */
 | |
|   final public Element getDocumentElement()
 | |
|   {
 | |
|     for (DomNode ctx = first; ctx != null; ctx = ctx.next)
 | |
|       {
 | |
|         if (ctx.nodeType == ELEMENT_NODE)
 | |
|           {
 | |
|             return (Element) ctx;
 | |
|           }
 | |
|       }
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns the document's DocumentType, or null.
 | |
|    */
 | |
|   final public DocumentType getDoctype()
 | |
|   {
 | |
|     for (DomNode ctx = first; ctx != null; ctx = ctx.next)
 | |
|       {
 | |
|       if (ctx.nodeType == DOCUMENT_TYPE_NODE)
 | |
|           {
 | |
|             return (DocumentType) ctx;
 | |
|           }
 | |
|       }
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns the document's DOMImplementation.
 | |
|    */
 | |
|   final public DOMImplementation getImplementation()
 | |
|   {
 | |
|     return implementation;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1 (relocated in DOM L2)</b>
 | |
|    * Returns the element with the specified "ID" attribute, or null.
 | |
|    *
 | |
|    * <p>Returns null unless {@link Consumer} was used to populate internal
 | |
|    * DTD declaration information, using package-private APIs.  If that
 | |
|    * internal DTD information is available, the document may be searched for
 | |
|    * the element with that ID.
 | |
|    */
 | |
|   public Element getElementById(String id)
 | |
|   {
 | |
|     if (id == null || id.length() == 0)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     DomDoctype doctype = (DomDoctype) getDoctype();
 | |
|     if (doctype != null && !doctype.hasIds())
 | |
|       {
 | |
|         doctype = null;
 | |
|       }
 | |
| 
 | |
|     // yes, this is linear in size of document.
 | |
|     // it'd be easy enough to maintain a hashtable.
 | |
|     Node current = getDocumentElement();
 | |
|     Node temp;
 | |
| 
 | |
|     if (current == null)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     while (current != this)
 | |
|       {
 | |
|         // done?
 | |
|         if (current.getNodeType() == ELEMENT_NODE)
 | |
|           {
 | |
|             DomElement element = (DomElement) current;
 | |
|             if (element.userIdAttrs != null)
 | |
|               {
 | |
|                 for (Iterator i = element.userIdAttrs.iterator();
 | |
|                      i.hasNext(); )
 | |
|                   {
 | |
|                     Node idAttr = (Node) i.next();
 | |
|                     if (id.equals(idAttr.getNodeValue()))
 | |
|                       {
 | |
|                         return element;
 | |
|                       }
 | |
|                   }
 | |
|               }
 | |
|             if (doctype != null)
 | |
|               {
 | |
|                 DTDElementTypeInfo info =
 | |
|                   doctype.getElementTypeInfo(current.getNodeName());
 | |
|                 if (info != null &&
 | |
|                     id.equals(element.getAttribute(info.idAttrName)))
 | |
|                   {
 | |
|                     return element;
 | |
|                   }
 | |
|               }
 | |
|             // xml:id
 | |
|             String xmlId = element.getAttribute("xml:id");
 | |
|             if (xmlId == null)
 | |
|               {
 | |
|                 xmlId = element.getAttributeNS(XMLConstants.XML_NS_URI,
 | |
|                                                "id");
 | |
|               }
 | |
|             if (id.equals(xmlId))
 | |
|               {
 | |
|                 return element;
 | |
|               }
 | |
|           }
 | |
| 
 | |
|         // descend?
 | |
|         if (current.hasChildNodes())
 | |
|           {
 | |
|             current = current.getFirstChild();
 | |
|             continue;
 | |
|           }
 | |
| 
 | |
|         // lateral?
 | |
|         temp = current.getNextSibling();
 | |
|         if (temp != null)
 | |
|           {
 | |
|             current = temp;
 | |
|             continue;
 | |
|           }
 | |
| 
 | |
|         // back up ...
 | |
|         do
 | |
|           {
 | |
|             temp = current.getParentNode();
 | |
|             if (temp == null)
 | |
|               {
 | |
|                 return null;
 | |
|               }
 | |
|             current = temp;
 | |
|             temp = current.getNextSibling();
 | |
|           }
 | |
|         while (temp == null);
 | |
|         current = temp;
 | |
|       }
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   private void checkNewChild(Node newChild)
 | |
|   {
 | |
|     if (newChild.getNodeType() == ELEMENT_NODE
 | |
|         && getDocumentElement() != null)
 | |
|       {
 | |
|         throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
 | |
|                                   "document element already present: " +
 | |
|                                   getDocumentElement(), newChild, 0);
 | |
|       }
 | |
|     if (newChild.getNodeType() == DOCUMENT_TYPE_NODE
 | |
|         && getDoctype() != null)
 | |
|       {
 | |
|         throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
 | |
|                                   "document type already present: " +
 | |
|                                   getDoctype(), newChild, 0);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Appends the specified node to this node's list of children,
 | |
|    * enforcing the constraints that there be only one root element
 | |
|    * and one document type child.
 | |
|    */
 | |
|   public Node appendChild(Node newChild)
 | |
|   {
 | |
|     if (checkingWellformedness)
 | |
|       {
 | |
|         checkNewChild(newChild);
 | |
|       }
 | |
|     return super.appendChild(newChild);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Inserts the specified node in this node's list of children,
 | |
|    * enforcing the constraints that there be only one root element
 | |
|    * and one document type child.
 | |
|    */
 | |
|   public Node insertBefore(Node newChild, Node refChild)
 | |
|   {
 | |
|     if (checkingWellformedness)
 | |
|       {
 | |
|         checkNewChild(newChild);
 | |
|       }
 | |
|     return super.insertBefore(newChild, refChild);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Replaces the specified node in this node's list of children,
 | |
|    * enforcing the constraints that there be only one root element
 | |
|    * and one document type child.
 | |
|    */
 | |
|   public Node replaceChild(Node newChild, Node refChild)
 | |
|   {
 | |
|     if (checkingWellformedness &&
 | |
|         ((newChild.getNodeType() == ELEMENT_NODE &&
 | |
|           refChild.getNodeType() != ELEMENT_NODE) ||
 | |
|          (newChild.getNodeType() == DOCUMENT_TYPE_NODE &&
 | |
|           refChild.getNodeType() != DOCUMENT_TYPE_NODE)))
 | |
|       {
 | |
|         checkNewChild(newChild);
 | |
|       }
 | |
|     return super.replaceChild(newChild, refChild);
 | |
|   }
 | |
| 
 | |
|   // NOTE:  DOM can't really tell when the name of an entity,
 | |
|   // notation, or PI must follow the namespace rules (excluding
 | |
|   // colons) instead of the XML rules (which allow them without
 | |
|   // much restriction).  That's an API issue.  verifyXmlName
 | |
|   // aims to enforce the XML rules, not the namespace rules.
 | |
| 
 | |
|   /**
 | |
|    * Throws a DOM exception if the specified name is not a legal XML 1.0
 | |
|    * Name.
 | |
|    * @deprecated This method is deprecated and may be removed in future
 | |
|    * versions of GNU JAXP
 | |
|    */
 | |
|   public static void verifyXmlName(String name)
 | |
|   {
 | |
|     // XXX why is this public?
 | |
|     checkName(name, false);
 | |
|   }
 | |
| 
 | |
|   static void checkName(String name, boolean xml11)
 | |
|   {
 | |
|     if (name == null)
 | |
|       {
 | |
|         throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0);
 | |
|       }
 | |
|     int len = name.length();
 | |
|     if (len == 0)
 | |
|       {
 | |
|         throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0);
 | |
|       }
 | |
| 
 | |
|     // dog: rewritten to use the rules for XML 1.0 and 1.1
 | |
| 
 | |
|     // Name start character
 | |
|     char c = name.charAt(0);
 | |
|     if (xml11)
 | |
|       {
 | |
|         // XML 1.1
 | |
|         if ((c < 0x0041 || c > 0x005a) &&
 | |
|             (c < 0x0061 || c > 0x007a) &&
 | |
|             c != ':' && c != '_' &&
 | |
|             (c < 0x00c0 || c > 0x00d6) &&
 | |
|             (c < 0x00d8 || c > 0x00f6) &&
 | |
|             (c < 0x00f8 || c > 0x02ff) &&
 | |
|             (c < 0x0370 || c > 0x037d) &&
 | |
|             (c < 0x037f || c > 0x1fff) &&
 | |
|             (c < 0x200c || c > 0x200d) &&
 | |
|             (c < 0x2070 || c > 0x218f) &&
 | |
|             (c < 0x2c00 || c > 0x2fef) &&
 | |
|             (c < 0x3001 || c > 0xd7ff) &&
 | |
|             (c < 0xf900 || c > 0xfdcf) &&
 | |
|             (c < 0xfdf0 || c > 0xfffd) &&
 | |
|             (c < 0x10000 || c > 0xeffff))
 | |
|           {
 | |
|             throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
 | |
|                                       name, null, c);
 | |
|           }
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         // XML 1.0
 | |
|         int type = Character.getType(c);
 | |
|         switch (type)
 | |
|           {
 | |
|           case Character.LOWERCASE_LETTER: // Ll
 | |
|           case Character.UPPERCASE_LETTER: // Lu
 | |
|           case Character.OTHER_LETTER: // Lo
 | |
|           case Character.TITLECASE_LETTER: // Lt
 | |
|           case Character.LETTER_NUMBER: // Nl
 | |
|             if ((c > 0xf900 && c < 0xfffe) ||
 | |
|                 (c >= 0x20dd && c <= 0x20e0))
 | |
|               {
 | |
|                 // Compatibility area and Unicode 2.0 exclusions
 | |
|                 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
 | |
|                                           name, null, c);
 | |
|               }
 | |
|             break;
 | |
|           default:
 | |
|             if (c != ':' && c != '_' && (c < 0x02bb || c > 0x02c1) &&
 | |
|                 c != 0x0559 && c != 0x06e5 && c != 0x06e6)
 | |
|               {
 | |
|                 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
 | |
|                                           name, null, c);
 | |
|               }
 | |
|           }
 | |
|       }
 | |
| 
 | |
|     // Subsequent characters
 | |
|     for (int i = 1; i < len; i++)
 | |
|       {
 | |
|         c = name.charAt(i);
 | |
|         if (xml11)
 | |
|           {
 | |
|             // XML 1.1
 | |
|             if ((c < 0x0041 || c > 0x005a) &&
 | |
|                 (c < 0x0061 || c > 0x007a) &&
 | |
|                 (c < 0x0030 || c > 0x0039) &&
 | |
|                 c != ':' && c != '_' && c != '-' && c != '.' &&
 | |
|                 (c < 0x00c0 || c > 0x00d6) &&
 | |
|                 (c < 0x00d8 || c > 0x00f6) &&
 | |
|                 (c < 0x00f8 || c > 0x02ff) &&
 | |
|                 (c < 0x0370 || c > 0x037d) &&
 | |
|                 (c < 0x037f || c > 0x1fff) &&
 | |
|                 (c < 0x200c || c > 0x200d) &&
 | |
|                 (c < 0x2070 || c > 0x218f) &&
 | |
|                 (c < 0x2c00 || c > 0x2fef) &&
 | |
|                 (c < 0x3001 || c > 0xd7ff) &&
 | |
|                 (c < 0xf900 || c > 0xfdcf) &&
 | |
|                 (c < 0xfdf0 || c > 0xfffd) &&
 | |
|                 (c < 0x10000 || c > 0xeffff) &&
 | |
|                 c != 0x00b7 &&
 | |
|                 (c < 0x0300 || c > 0x036f) &&
 | |
|                 (c < 0x203f || c > 0x2040))
 | |
|               {
 | |
|                 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, name,
 | |
|                                           null, c);
 | |
|               }
 | |
|           }
 | |
|         else
 | |
|           {
 | |
|             // XML 1.0
 | |
|             int type = Character.getType(c);
 | |
|             switch (type)
 | |
|               {
 | |
|               case Character.LOWERCASE_LETTER: // Ll
 | |
|               case Character.UPPERCASE_LETTER: // Lu
 | |
|               case Character.DECIMAL_DIGIT_NUMBER: // Nd
 | |
|               case Character.OTHER_LETTER: // Lo
 | |
|               case Character.TITLECASE_LETTER: // Lt
 | |
|               case Character.LETTER_NUMBER: // Nl
 | |
|               case Character.COMBINING_SPACING_MARK: // Mc
 | |
|               case Character.ENCLOSING_MARK: // Me
 | |
|               case Character.NON_SPACING_MARK: // Mn
 | |
|               case Character.MODIFIER_LETTER: // Lm
 | |
|                 if ((c > 0xf900 && c < 0xfffe) ||
 | |
|                     (c >= 0x20dd && c <= 0x20e0))
 | |
|                   {
 | |
|                     // Compatibility area and Unicode 2.0 exclusions
 | |
|                     throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
 | |
|                                               name, null, c);
 | |
|                   }
 | |
|                 break;
 | |
|               default:
 | |
|                 if (c != '-' && c != '.' && c != ':' && c != '_' &&
 | |
|                     c != 0x0387 && (c < 0x02bb || c > 0x02c1) &&
 | |
|                     c != 0x0559 && c != 0x06e5 && c != 0x06e6 && c != 0x00b7)
 | |
|                   {
 | |
|                     throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
 | |
|                                               name, null, c);
 | |
|                   }
 | |
|               }
 | |
|           }
 | |
|       }
 | |
| 
 | |
|     // FIXME characters with a font or compatibility decomposition (i.e.
 | |
|     // those with a "compatibility formatting tag" in field 5 of the
 | |
|     // database -- marked by field 5 beginning with a "<") are not allowed.
 | |
|   }
 | |
| 
 | |
|   // package private
 | |
|   static void checkNCName(String name, boolean xml11)
 | |
|   {
 | |
|     checkName(name, xml11);
 | |
|     int len = name.length();
 | |
|     int index = name.indexOf(':');
 | |
|     if (index != -1)
 | |
|       {
 | |
|         if (index == 0 || index == (len - 1) || name.lastIndexOf(':') != index)
 | |
|           {
 | |
|             throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0);
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   // package private
 | |
|   static void checkChar(String value, boolean xml11)
 | |
|   {
 | |
|     char[] chars = value.toCharArray();
 | |
|     checkChar(chars, 0, chars.length, xml11);
 | |
|   }
 | |
| 
 | |
|   static void checkChar(char[] buf, int off, int len, boolean xml11)
 | |
|   {
 | |
|     for (int i = 0; i < len; i++)
 | |
|       {
 | |
|         char c = buf[i];
 | |
| 
 | |
|         // assume surrogate pairing checks out OK, for simplicity
 | |
|         if ((c >= 0x0020 && c <= 0xd7ff) ||
 | |
|             (c == 0x000a || c == 0x000d || c == 0x0009) ||
 | |
|             (c >= 0xe000 && c <= 0xfffd) ||
 | |
|             (c >= 0x10000 && c <= 0x10ffff))
 | |
|           {
 | |
|             continue;
 | |
|           }
 | |
|         if (xml11)
 | |
|           {
 | |
|             if ((c >= 0x0001 && c <= 0x001f) ||
 | |
|                 (c >= 0x007f && c <= 0x0084) ||
 | |
|                 (c >= 0x0086 && c <= 0x009f))
 | |
|               {
 | |
|                 continue;
 | |
|               }
 | |
|           }
 | |
|         throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
 | |
|                                   new String(buf, off, len), null, c);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns a newly created element with the specified name.
 | |
|    * The node name of the created element will be equal to {@code name}.
 | |
|    * The namespace, prefix and local name will all be {@code null}.
 | |
|    */
 | |
|   public Element createElement(String name)
 | |
|   {
 | |
|     Element element;
 | |
| 
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         checkName(name, "1.1".equals(version));
 | |
|       }
 | |
|     if (name.startsWith("xml:"))
 | |
|       {
 | |
|         element = createElementNS(null, name);
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         DomElement domElement = new DomElement(this, null, name, null, null);
 | |
|         element = domElement;
 | |
|       }
 | |
|     if (defaultAttributes)
 | |
|       setDefaultAttributes(element, name);
 | |
|     return element;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L2</b>
 | |
|    * Returns a newly created element with the specified name
 | |
|    * and namespace information.
 | |
|    */
 | |
|   public Element createElementNS(String namespaceURI, String name)
 | |
|   {
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         checkNCName(name, "1.1".equals(version));
 | |
|       }
 | |
| 
 | |
|     if ("".equals(namespaceURI))
 | |
|       {
 | |
|         namespaceURI = null;
 | |
|       }
 | |
|     if (name.startsWith("xml:"))
 | |
|       {
 | |
|         if (namespaceURI != null
 | |
|             && !XMLConstants.XML_NS_URI.equals(namespaceURI))
 | |
|           {
 | |
|             throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                                       "xml namespace is always " +
 | |
|                                       XMLConstants.XML_NS_URI, this, 0);
 | |
|           }
 | |
|         namespaceURI = XMLConstants.XML_NS_URI;
 | |
|       }
 | |
|     else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
 | |
|              name.startsWith("xmlns:"))
 | |
|       {
 | |
|         throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                                   "xmlns is reserved", this, 0);
 | |
|       }
 | |
|     else if (namespaceURI == null && name.indexOf(':') != -1)
 | |
|       {
 | |
|         throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                                   "prefixed name '" + name +
 | |
|                                   "' needs a URI", this, 0);
 | |
|       }
 | |
| 
 | |
|     Element  element = new DomElement(this, namespaceURI, name);
 | |
|     if (defaultAttributes)
 | |
|       setDefaultAttributes(element, name);
 | |
|     return element;
 | |
|   }
 | |
| 
 | |
|   private void setDefaultAttributes(Element element, String name)
 | |
|   {
 | |
|     DomDoctype doctype = (DomDoctype) getDoctype();
 | |
|     if (doctype == null)
 | |
|       {
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|     // default any attributes that need it
 | |
|     DTDElementTypeInfo info = doctype.getElementTypeInfo(name);
 | |
|     if (info != null)
 | |
|       {
 | |
|         for (Iterator i = info.attributes(); i != null && i.hasNext(); )
 | |
|           {
 | |
|             DTDAttributeTypeInfo attr = (DTDAttributeTypeInfo) i.next();
 | |
|             String value = attr.value;
 | |
|             if ("#IMPLIED".equals(attr.mode) && value == null)
 | |
|               continue;
 | |
|             DomAttr node = (DomAttr) createAttribute(attr.name);
 | |
| 
 | |
|             if (value == null)
 | |
|               {
 | |
|                 value = "";
 | |
|               }
 | |
|             node.setValue(value);
 | |
|             node.setSpecified(false);
 | |
|             element.setAttributeNode(node);
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns a newly created document fragment.
 | |
|    */
 | |
|   public DocumentFragment createDocumentFragment()
 | |
|   {
 | |
|     return new DomDocumentFragment(this);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns a newly created text node with the specified value.
 | |
|    */
 | |
|   public Text createTextNode(String value)
 | |
|   {
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         checkChar(value, "1.1".equals(version));
 | |
|       }
 | |
|     return new DomText(this, value);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns a newly created text node with the specified value.
 | |
|    */
 | |
|   public Text createTextNode(char[] buf, int off, int len)
 | |
|   {
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         checkChar(buf, off, len, "1.1".equals(version));
 | |
|       }
 | |
|     return new DomText(this, buf, off, len);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns a newly created comment node with the specified value.
 | |
|    */
 | |
|   public Comment createComment(String value)
 | |
|   {
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         checkChar(value, "1.1".equals(version));
 | |
|       }
 | |
|     return new DomComment(this, value);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns a newly created CDATA section node with the specified value.
 | |
|    */
 | |
|   public CDATASection createCDATASection(String value)
 | |
|   {
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         checkChar(value, "1.1".equals(version));
 | |
|       }
 | |
|     return new DomCDATASection(this, value);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns a newly created CDATA section node with the specified value.
 | |
|    */
 | |
|   public CDATASection createCDATASection(char[] buf, int off, int len)
 | |
|   {
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         checkChar(buf, off, len, "1.1".equals(version));
 | |
|       }
 | |
|     return new DomCDATASection(this, buf, off, len);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns a newly created processing instruction.
 | |
|    */
 | |
|   public ProcessingInstruction createProcessingInstruction(String target,
 | |
|                                                            String data)
 | |
|   {
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         boolean xml11 = "1.1".equals(version);
 | |
|         checkName(target, xml11);
 | |
|         if ("xml".equalsIgnoreCase(target))
 | |
|           {
 | |
|             throw new DomDOMException(DOMException.SYNTAX_ERR,
 | |
|                                       "illegal PI target name",
 | |
|                                       this, 0);
 | |
|           }
 | |
|         checkChar(data, xml11);
 | |
|       }
 | |
|     return new DomProcessingInstruction(this, target, data);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns a newly created attribute with the specified name.
 | |
|    */
 | |
|   public Attr createAttribute(String name)
 | |
|   {
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         checkName(name, "1.1".equals(version));
 | |
|       }
 | |
|     if (name.startsWith("xml:"))
 | |
|       {
 | |
|         return createAttributeNS(XMLConstants.XML_NS_URI, name);
 | |
|       }
 | |
|     else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
 | |
|              name.startsWith("xmlns:"))
 | |
|       {
 | |
|         return createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, name);
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         DomAttr ret = new DomAttr(this, null, name, null, null);
 | |
|         return ret;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L2</b>
 | |
|    * Returns a newly created attribute with the specified name
 | |
|    * and namespace information.
 | |
|    */
 | |
|   public Attr createAttributeNS(String namespaceURI, String name)
 | |
|   {
 | |
|     if (checkingCharacters)
 | |
|       {
 | |
|         checkNCName(name, "1.1".equals(version));
 | |
|       }
 | |
| 
 | |
|     if ("".equals(namespaceURI))
 | |
|       {
 | |
|         namespaceURI = null;
 | |
|       }
 | |
|     if (name.startsWith ("xml:"))
 | |
|       {
 | |
|         if (namespaceURI == null)
 | |
|           {
 | |
|             namespaceURI = XMLConstants.XML_NS_URI;
 | |
|           }
 | |
|         else if (!XMLConstants.XML_NS_URI.equals(namespaceURI))
 | |
|           {
 | |
|             throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                                       "xml namespace is always " +
 | |
|                                       XMLConstants.XML_NS_URI,
 | |
|                                       this, 0);
 | |
|           }
 | |
|       }
 | |
|     else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
 | |
|              name.startsWith("xmlns:"))
 | |
|       {
 | |
|         if (namespaceURI == null)
 | |
|           {
 | |
|             namespaceURI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
 | |
|           }
 | |
|         else if (!XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI))
 | |
|           {
 | |
|             throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                                       "xmlns namespace must be " +
 | |
|                                       XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
 | |
|                                       this, 0);
 | |
|           }
 | |
|       }
 | |
|     else if (namespaceURI == null && name.indexOf(':') != -1)
 | |
|       {
 | |
|         throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                         "prefixed name needs a URI: " + name, this, 0);
 | |
|       }
 | |
|     return new DomAttr(this, namespaceURI, name);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L1</b>
 | |
|    * Returns a newly created reference to the specified entity.
 | |
|    * The caller should populate this with the appropriate children
 | |
|    * and then mark it as readonly.
 | |
|    *
 | |
|    * @see DomNode#makeReadonly
 | |
|    */
 | |
|   public EntityReference createEntityReference(String name)
 | |
|   {
 | |
|     DomEntityReference ret = new DomEntityReference(this, name);
 | |
|     DocumentType doctype = getDoctype();
 | |
|     if (doctype != null)
 | |
|       {
 | |
|         DomEntity ent = (DomEntity) doctype.getEntities().getNamedItem(name);
 | |
|         if (ent != null)
 | |
|           {
 | |
|             for (DomNode ctx = ent.first; ctx != null; ctx = ctx.next)
 | |
|               {
 | |
|                 ret.appendChild(ctx.cloneNode(true));
 | |
|               }
 | |
|           }
 | |
|       }
 | |
|     ret.makeReadonly();
 | |
|     return ret;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L2</b>
 | |
|    * Makes a copy of the specified node, with all nodes "owned" by
 | |
|    * this document and with children optionally copied.  This type
 | |
|    * of standard utility has become, well, a standard utility.
 | |
|    *
 | |
|    * <p> Note that EntityReference nodes created through this method (either
 | |
|    * directly, or recursively) never have children, and that there is no
 | |
|    * portable way to associate them with such children.
 | |
|    *
 | |
|    * <p> Note also that there is no requirement that the specified node
 | |
|    * be associated with a different document.  This differs from the
 | |
|    * <em>cloneNode</em> operation in that the node itself is not given
 | |
|    * an opportunity to participate, so that any information managed
 | |
|    * by node subclasses will be lost.
 | |
|    */
 | |
|   public Node importNode(Node src, boolean deep)
 | |
|   {
 | |
|     Node dst = null;
 | |
|     switch (src.getNodeType())
 | |
|       {
 | |
|       case TEXT_NODE:
 | |
|         dst = createTextNode(src.getNodeValue());
 | |
|         break;
 | |
|       case CDATA_SECTION_NODE:
 | |
|         dst = createCDATASection(src.getNodeValue());
 | |
|         break;
 | |
|       case COMMENT_NODE:
 | |
|         dst = createComment(src.getNodeValue());
 | |
|         break;
 | |
|       case PROCESSING_INSTRUCTION_NODE:
 | |
|         dst = createProcessingInstruction(src.getNodeName(),
 | |
|                                           src.getNodeValue());
 | |
|         break;
 | |
|       case NOTATION_NODE:
 | |
|         // NOTE:  There's no standard way to create
 | |
|         // these, or add them to a doctype.  Useless.
 | |
|         Notation notation = (Notation) src;
 | |
|         dst = new DomNotation(this, notation.getNodeName(),
 | |
|                               notation.getPublicId(),
 | |
|                               notation.getSystemId());
 | |
|         break;
 | |
|       case ENTITY_NODE:
 | |
|         // NOTE:  There's no standard way to create
 | |
|         // these, or add them to a doctype.  Useless.
 | |
|         Entity entity = (Entity) src;
 | |
|         dst = new DomEntity(this, entity.getNodeName(),
 | |
|                             entity.getPublicId(),
 | |
|                             entity.getSystemId(),
 | |
|                             entity.getNotationName());
 | |
|         if (deep)
 | |
|           {
 | |
|             for (Node ctx = src.getFirstChild(); ctx != null;
 | |
|                  ctx = ctx.getNextSibling())
 | |
|               {
 | |
|                 dst.appendChild(importNode(ctx, deep));
 | |
|               }
 | |
|           }
 | |
|         break;
 | |
|       case ENTITY_REFERENCE_NODE:
 | |
|         dst = createEntityReference(src.getNodeName());
 | |
|         break;
 | |
|       case DOCUMENT_FRAGMENT_NODE:
 | |
|         dst = new DomDocumentFragment(this);
 | |
|         if (deep)
 | |
|           {
 | |
|             for (Node ctx = src.getFirstChild(); ctx != null;
 | |
|                  ctx = ctx.getNextSibling())
 | |
|               {
 | |
|                 dst.appendChild(importNode(ctx, deep));
 | |
|               }
 | |
|           }
 | |
|         break;
 | |
|       case ATTRIBUTE_NODE:
 | |
|         String attr_nsuri = src.getNamespaceURI();
 | |
|         if (attr_nsuri != null)
 | |
|           {
 | |
|             dst = createAttributeNS(attr_nsuri, src.getNodeName());
 | |
|           }
 | |
|         else
 | |
|           {
 | |
|             dst = createAttribute(src.getNodeName());
 | |
|           }
 | |
|         // this is _always_ done regardless of "deep" setting
 | |
|         for (Node ctx = src.getFirstChild(); ctx != null;
 | |
|              ctx = ctx.getNextSibling())
 | |
|           {
 | |
|             dst.appendChild(importNode(ctx, false));
 | |
|           }
 | |
|         break;
 | |
|       case ELEMENT_NODE:
 | |
|         String elem_nsuri = src.getNamespaceURI();
 | |
|         if (elem_nsuri != null)
 | |
|           {
 | |
|             dst = createElementNS(elem_nsuri, src.getNodeName());
 | |
|           }
 | |
|         else
 | |
|           {
 | |
|             dst = createElement(src.getNodeName());
 | |
|           }
 | |
|         NamedNodeMap srcAttrs = src.getAttributes();
 | |
|         NamedNodeMap dstAttrs = dst.getAttributes();
 | |
|         int len = srcAttrs.getLength();
 | |
|         for (int i = 0; i < len; i++)
 | |
|           {
 | |
|             Attr a = (Attr) srcAttrs.item(i);
 | |
|             Attr dflt;
 | |
| 
 | |
|             // maybe update defaulted attributes
 | |
|             dflt = (Attr) dstAttrs.getNamedItem(a.getNodeName());
 | |
|             if (dflt != null)
 | |
|               {
 | |
|                 String newval = a.getNodeValue();
 | |
|                 if (!dflt.getNodeValue().equals(newval)
 | |
|                     || a.getSpecified () == true)
 | |
|                   {
 | |
|                     dflt.setNodeValue (newval);
 | |
|                   }
 | |
|                 continue;
 | |
|               }
 | |
| 
 | |
|             dstAttrs.setNamedItem((Attr) importNode(a, false));
 | |
|           }
 | |
|         if (deep)
 | |
|           {
 | |
|             for (Node ctx = src.getFirstChild(); ctx != null;
 | |
|                  ctx = ctx.getNextSibling())
 | |
|               {
 | |
|                 dst.appendChild(importNode(ctx, true));
 | |
|               }
 | |
|           }
 | |
|         break;
 | |
|         // can't import document or doctype nodes
 | |
|       case DOCUMENT_NODE:
 | |
|       case DOCUMENT_TYPE_NODE:
 | |
|         // FALLTHROUGH
 | |
|         // can't import unrecognized or nonstandard nodes
 | |
|       default:
 | |
|         throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR, null, src, 0);
 | |
|       }
 | |
| 
 | |
|     // FIXME cleanup a bit -- for deep copies, copy those
 | |
|     // children in one place, here (code sharing is healthy)
 | |
| 
 | |
|     if (src instanceof DomNode)
 | |
|       {
 | |
|         ((DomNode) src).notifyUserDataHandlers(UserDataHandler.NODE_IMPORTED,
 | |
|                                                src, dst);
 | |
|       }
 | |
|     return dst;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>DOM L2 (Traversal)</b>
 | |
|    * Returns a newly created node iterator.  Don't forget to detach
 | |
|    * this iterator when you're done using it!
 | |
|    *
 | |
|    * @see DomIterator
 | |
|    */
 | |
|   public NodeIterator createNodeIterator(Node root,
 | |
|                                          int whatToShow,
 | |
|                                          NodeFilter filter,
 | |
|                                          boolean expandEntities)
 | |
|   {
 | |
|     return new DomNodeIterator(root, whatToShow, filter, expandEntities,
 | |
|                                false);
 | |
|   }
 | |
| 
 | |
|   public TreeWalker createTreeWalker(Node root,
 | |
|                                      int whatToShow,
 | |
|                                      NodeFilter filter,
 | |
|                                      boolean expandEntities)
 | |
|   {
 | |
|     return new DomNodeIterator(root, whatToShow, filter, expandEntities,
 | |
|                                true);
 | |
|   }
 | |
| 
 | |
|   // DOM Level 3 methods
 | |
| 
 | |
|   /**
 | |
|    * DOM L3
 | |
|    */
 | |
|   public String getInputEncoding()
 | |
|   {
 | |
|     return inputEncoding;
 | |
|   }
 | |
| 
 | |
|   public void setInputEncoding(String inputEncoding)
 | |
|   {
 | |
|     this.inputEncoding = inputEncoding;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * DOM L3
 | |
|    */
 | |
|   public String getXmlEncoding()
 | |
|   {
 | |
|     return encoding;
 | |
|   }
 | |
| 
 | |
|   public void setXmlEncoding(String encoding)
 | |
|   {
 | |
|     this.encoding = encoding;
 | |
|   }
 | |
| 
 | |
|   public boolean getXmlStandalone()
 | |
|   {
 | |
|     return standalone;
 | |
|   }
 | |
| 
 | |
|   public void setXmlStandalone(boolean xmlStandalone)
 | |
|   {
 | |
|     standalone = xmlStandalone;
 | |
|   }
 | |
| 
 | |
|   public String getXmlVersion()
 | |
|   {
 | |
|     return version;
 | |
|   }
 | |
| 
 | |
|   public void setXmlVersion(String xmlVersion)
 | |
|   {
 | |
|     if (xmlVersion == null)
 | |
|       {
 | |
|         xmlVersion = "1.0";
 | |
|       }
 | |
|     if ("1.0".equals(xmlVersion) ||
 | |
|         "1.1".equals(xmlVersion))
 | |
|       {
 | |
|         version = xmlVersion;
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   public boolean getStrictErrorChecking()
 | |
|   {
 | |
|     return checkingCharacters;
 | |
|   }
 | |
| 
 | |
|   public void setStrictErrorChecking(boolean strictErrorChecking)
 | |
|   {
 | |
|     checkingCharacters = strictErrorChecking;
 | |
|   }
 | |
| 
 | |
|   public String lookupPrefix(String namespaceURI)
 | |
|   {
 | |
|     Node root = getDocumentElement();
 | |
|     return (root == null) ? null : root.lookupPrefix(namespaceURI);
 | |
|   }
 | |
| 
 | |
|   public boolean isDefaultNamespace(String namespaceURI)
 | |
|   {
 | |
|     Node root = getDocumentElement();
 | |
|     return (root == null) ? false : root.isDefaultNamespace(namespaceURI);
 | |
|   }
 | |
| 
 | |
|   public String lookupNamespaceURI(String prefix)
 | |
|   {
 | |
|     Node root = getDocumentElement();
 | |
|     return (root == null) ? null : root.lookupNamespaceURI(prefix);
 | |
|   }
 | |
| 
 | |
|   public String getBaseURI()
 | |
|   {
 | |
|     return getDocumentURI();
 | |
|     /*
 | |
|     Node root = getDocumentElement();
 | |
|     if (root != null)
 | |
|       {
 | |
|         NamedNodeMap attrs = root.getAttributes();
 | |
|         Node xmlBase = attrs.getNamedItemNS(XMLConstants.XML_NS_URI, "base");
 | |
|         if (xmlBase != null)
 | |
|           {
 | |
|             return xmlBase.getNodeValue();
 | |
|           }
 | |
|       }
 | |
|     return systemId;
 | |
|     */
 | |
|   }
 | |
| 
 | |
|   public String getDocumentURI()
 | |
|   {
 | |
|     return systemId;
 | |
|   }
 | |
| 
 | |
|   public void setDocumentURI(String documentURI)
 | |
|   {
 | |
|     systemId = documentURI;
 | |
|   }
 | |
| 
 | |
|   public Node adoptNode(Node source)
 | |
|   {
 | |
|     int sourceNodeType = source.getNodeType();
 | |
|     switch (sourceNodeType)
 | |
|       {
 | |
|       case DOCUMENT_NODE:
 | |
|       case DOCUMENT_TYPE_NODE:
 | |
|         throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
 | |
|       case ENTITY_NODE:
 | |
|       case NOTATION_NODE:
 | |
|         throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
 | |
|       }
 | |
|     if (source instanceof DomNode)
 | |
|       {
 | |
|         // GNU native
 | |
|         DomNode src = (DomNode) source;
 | |
|         DomNode dst = src;
 | |
|         if (dst.parent != null)
 | |
|           {
 | |
|             dst = (DomNode) dst.cloneNode(true);
 | |
|           }
 | |
|         dst.setOwner(this);
 | |
|         src.notifyUserDataHandlers(UserDataHandler.NODE_ADOPTED, src, dst);
 | |
|         return dst;
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         // Some other implementation
 | |
|         Node dst = null;
 | |
|         switch (sourceNodeType)
 | |
|           {
 | |
|           case Node.ATTRIBUTE_NODE:
 | |
|               {
 | |
|                 Attr src = (Attr) source;
 | |
|                 String nodeName = src.getNodeName();
 | |
|                 String localName = src.getLocalName();
 | |
|                 String namespaceUri = src.getNamespaceURI();
 | |
|                 dst = (localName == null) ?
 | |
|                   createAttribute(nodeName) :
 | |
|                   createAttributeNS(namespaceUri, nodeName);
 | |
|                 adoptChildren(src, dst);
 | |
|                 break;
 | |
|               }
 | |
|           case Node.CDATA_SECTION_NODE:
 | |
|               {
 | |
|                 CDATASection src = (CDATASection) source;
 | |
|                 dst = createCDATASection(src.getData());
 | |
|                 break;
 | |
|               }
 | |
|           case Node.COMMENT_NODE:
 | |
|               {
 | |
|                 Comment src = (Comment) source;
 | |
|                 dst = createComment(src.getData());
 | |
|                 break;
 | |
|               }
 | |
|           case Node.DOCUMENT_FRAGMENT_NODE:
 | |
|               {
 | |
|                 DocumentFragment src = (DocumentFragment) source;
 | |
|                 dst = createDocumentFragment();
 | |
|                 adoptChildren(src, dst);
 | |
|                 break;
 | |
|               }
 | |
|           case Node.ELEMENT_NODE:
 | |
|               {
 | |
|                 Element src = (Element) source;
 | |
|                 String nodeName = src.getNodeName();
 | |
|                 String localName = src.getLocalName();
 | |
|                 String namespaceUri = src.getNamespaceURI();
 | |
|                 dst = (localName == null) ?
 | |
|                   createElement(nodeName) :
 | |
|                   createElementNS(namespaceUri, nodeName);
 | |
|                 adoptAttributes(src, dst);
 | |
|                 adoptChildren(src, dst);
 | |
|                 break;
 | |
|               }
 | |
|           case Node.ENTITY_REFERENCE_NODE:
 | |
|               {
 | |
|                 EntityReference src = (EntityReference) source;
 | |
|                 dst = createEntityReference(src.getNodeName());
 | |
|                 adoptChildren(src, dst);
 | |
|                 break;
 | |
|               }
 | |
|           case Node.PROCESSING_INSTRUCTION_NODE:
 | |
|               {
 | |
|                 ProcessingInstruction src = (ProcessingInstruction) source;
 | |
|                 dst = createProcessingInstruction(src.getTarget(),
 | |
|                                                   src.getData());
 | |
|                 break;
 | |
|               }
 | |
|           case Node.TEXT_NODE:
 | |
|               {
 | |
|                 Text src = (Text) source;
 | |
|                 dst = createTextNode(src.getData());
 | |
|                 break;
 | |
|               }
 | |
|           }
 | |
|         return dst;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   void adoptChildren(Node src, Node dst)
 | |
|   {
 | |
|     Node node = src.getFirstChild();
 | |
|     while (node != null)
 | |
|       {
 | |
|         Node next = node.getNextSibling();
 | |
|         dst.appendChild(adoptNode(node));
 | |
|         node = next;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   void adoptAttributes(Node src, Node dst)
 | |
|   {
 | |
|     NamedNodeMap srcAttrs = src.getAttributes();
 | |
|     NamedNodeMap dstAttrs = dst.getAttributes();
 | |
|     int len = srcAttrs.getLength();
 | |
|     for (int i = 0; i < len; i++)
 | |
|       {
 | |
|         Node node = srcAttrs.item(i);
 | |
|         String localName = node.getLocalName();
 | |
|         if (localName == null)
 | |
|           {
 | |
|             dstAttrs.setNamedItem(adoptNode(node));
 | |
|           }
 | |
|         else
 | |
|           {
 | |
|             dstAttrs.setNamedItemNS(adoptNode(node));
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   public DOMConfiguration getDomConfig()
 | |
|   {
 | |
|     if (config == null)
 | |
|       {
 | |
|         config = new DomDocumentConfiguration();
 | |
|       }
 | |
|     return config;
 | |
|   }
 | |
| 
 | |
|   public boolean isEqualNode(Node arg)
 | |
|   {
 | |
|     if (!super.isEqualNode(arg))
 | |
|       return false;
 | |
|     Document d = (Document) arg;
 | |
|     String dversion = d.getXmlVersion();
 | |
|     if (dversion == null || !dversion.equals(version))
 | |
|       return false;
 | |
|     boolean dstandalone = d.getXmlStandalone();
 | |
|     if (dstandalone != standalone)
 | |
|       return false;
 | |
|     String dencoding = d.getXmlEncoding();
 | |
|     if (dencoding == null || dencoding.equalsIgnoreCase("UTF-8"))
 | |
|       {
 | |
|         if (encoding != null && !encoding.equalsIgnoreCase("UTF-8"))
 | |
|           return false;
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         if (!dencoding.equals(encoding))
 | |
|           return false;
 | |
|       }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   public void normalizeDocument()
 | |
|   {
 | |
|     boolean save = building;
 | |
|     building = true;
 | |
|     normalizeNode(this);
 | |
|     building = save;
 | |
|   }
 | |
| 
 | |
|   void normalizeNode(DomNode node)
 | |
|   {
 | |
|     node.normalize();
 | |
|     if (config != null)
 | |
|       {
 | |
|         switch (node.nodeType)
 | |
|           {
 | |
|           case CDATA_SECTION_NODE:
 | |
|             if (!config.cdataSections)
 | |
|               {
 | |
|                 // replace CDATA section with text node
 | |
|                 Text text = createTextNode(node.getNodeValue());
 | |
|                 node.parent.insertBefore(text, node);
 | |
|                 node.parent.removeChild(node);
 | |
|                 // merge adjacent text nodes
 | |
|                 String data = text.getWholeText();
 | |
|                 node = (DomNode) text.replaceWholeText(data);
 | |
|               }
 | |
|             else if (config.splitCdataSections)
 | |
|               {
 | |
|                 String value = node.getNodeValue();
 | |
|                 int i = value.indexOf("]]>");
 | |
|                 while (i != -1)
 | |
|                   {
 | |
|                     Node node2 = createCDATASection(value.substring(0, i));
 | |
|                     node.parent.insertBefore(node2, node);
 | |
|                     value = value.substring(i + 3);
 | |
|                     node.setNodeValue(value);
 | |
|                     i = value.indexOf("]]>");
 | |
|                   }
 | |
|               }
 | |
|             break;
 | |
|           case COMMENT_NODE:
 | |
|             if (!config.comments)
 | |
|               {
 | |
|                 node.parent.removeChild(node);
 | |
|               }
 | |
|             break;
 | |
|           case TEXT_NODE:
 | |
|             if (!config.elementContentWhitespace &&
 | |
|                 ((Text) node).isElementContentWhitespace())
 | |
|               {
 | |
|                 node.parent.removeChild(node);
 | |
|               }
 | |
|             break;
 | |
|           case ENTITY_REFERENCE_NODE:
 | |
|             if (!config.entities)
 | |
|               {
 | |
|                 for (DomNode ctx = node.first; ctx != null; )
 | |
|                   {
 | |
|                     DomNode ctxNext = ctx.next;
 | |
|                     node.parent.insertBefore(ctx, node);
 | |
|                     ctx = ctxNext;
 | |
|                   }
 | |
|                 node.parent.removeChild(node);
 | |
|               }
 | |
|             break;
 | |
|           case ELEMENT_NODE:
 | |
|             if (!config.namespaceDeclarations)
 | |
|               {
 | |
|                 DomNamedNodeMap attrs =
 | |
|                   (DomNamedNodeMap) node.getAttributes();
 | |
|                 boolean aro = attrs.readonly;
 | |
|                 attrs.readonly = false; // Ensure we can delete if necessary
 | |
|                 int len = attrs.getLength();
 | |
|                 for (int i = 0; i < len; i++)
 | |
|                   {
 | |
|                     Node attr = attrs.item(i);
 | |
|                     String namespace = attr.getNamespaceURI();
 | |
|                     if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespace))
 | |
|                       {
 | |
|                         attrs.removeNamedItemNS(namespace,
 | |
|                                                 attr.getLocalName());
 | |
|                         i--;
 | |
|                         len--;
 | |
|                       }
 | |
|                   }
 | |
|                 attrs.readonly = aro;
 | |
|               }
 | |
|             break;
 | |
|           }
 | |
|       }
 | |
|     for (DomNode ctx = node.first; ctx != null; )
 | |
|       {
 | |
|         DomNode ctxNext = ctx.next;
 | |
|         normalizeNode(ctx);
 | |
|         ctx = ctxNext;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   public Node renameNode(Node n, String namespaceURI, String qualifiedName)
 | |
|     throws DOMException
 | |
|   {
 | |
|     if (n instanceof DomNsNode)
 | |
|       {
 | |
|         DomNsNode src = (DomNsNode) n;
 | |
|         if (src == null)
 | |
|           {
 | |
|             throw new DomDOMException(DOMException.NOT_FOUND_ERR);
 | |
|           }
 | |
|         if (src.owner != this)
 | |
|           {
 | |
|             throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
 | |
|                                       null, src, 0);
 | |
|           }
 | |
|         boolean xml11 = "1.1".equals(version);
 | |
|         checkName(qualifiedName, xml11);
 | |
|         int ci = qualifiedName.indexOf(':');
 | |
|         if ("".equals(namespaceURI))
 | |
|           {
 | |
|             namespaceURI = null;
 | |
|           }
 | |
|         if (namespaceURI != null)
 | |
|           {
 | |
|             checkNCName(qualifiedName, xml11);
 | |
|             String prefix = (ci == -1) ? "" :
 | |
|               qualifiedName.substring(0, ci);
 | |
|             if (XMLConstants.XML_NS_PREFIX.equals(prefix) &&
 | |
|                 !XMLConstants.XML_NS_URI.equals(namespaceURI))
 | |
|               {
 | |
|                 throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                                 "xml namespace must be " +
 | |
|                                 XMLConstants.XML_NS_URI, src, 0);
 | |
|               }
 | |
|             else if (src.nodeType == ATTRIBUTE_NODE &&
 | |
|                      (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) ||
 | |
|                       XMLConstants.XMLNS_ATTRIBUTE.equals(qualifiedName)) &&
 | |
|                      !XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI))
 | |
|               {
 | |
|                 throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                                 "xmlns namespace must be " +
 | |
|                                 XMLConstants.XMLNS_ATTRIBUTE_NS_URI, src, 0);
 | |
|               }
 | |
|             if (XMLConstants.XML_NS_URI.equals(namespaceURI) &&
 | |
|                 !XMLConstants.XML_NS_PREFIX.equals(prefix))
 | |
|               {
 | |
|                 throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                                 "xml namespace must be " +
 | |
|                                 XMLConstants.XML_NS_URI, src, 0);
 | |
|               }
 | |
|             else if (src.nodeType == ATTRIBUTE_NODE &&
 | |
|                      XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI) &&
 | |
|                      !(XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) ||
 | |
|                        XMLConstants.XMLNS_ATTRIBUTE.equals(qualifiedName)))
 | |
|               {
 | |
|                 throw new DomDOMException(DOMException.NAMESPACE_ERR,
 | |
|                                 "xmlns namespace must be " +
 | |
|                                 XMLConstants.XMLNS_ATTRIBUTE_NS_URI, src, 0);
 | |
|               }
 | |
| 
 | |
|           }
 | |
|         src.setNodeName(qualifiedName);
 | |
|         src.setNamespaceURI(namespaceURI);
 | |
|         src.notifyUserDataHandlers(UserDataHandler.NODE_RENAMED, src, src);
 | |
|         // TODO MutationNameEvents
 | |
|         // DOMElementNameChanged or DOMAttributeNameChanged
 | |
|         return src;
 | |
|       }
 | |
|     throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR, null, n, 0);
 | |
|   }
 | |
| 
 | |
|   // -- XPathEvaluator --
 | |
| 
 | |
|   public XPathExpression createExpression(String expression,
 | |
|                                           XPathNSResolver resolver)
 | |
|     throws XPathException, DOMException
 | |
|   {
 | |
|     return new DomXPathExpression(this, expression, resolver);
 | |
|   }
 | |
| 
 | |
|   public XPathNSResolver createNSResolver(Node nodeResolver)
 | |
|   {
 | |
|     return new DomXPathNSResolver(nodeResolver);
 | |
|   }
 | |
| 
 | |
|   public Object evaluate(String expression,
 | |
|                          Node contextNode,
 | |
|                          XPathNSResolver resolver,
 | |
|                          short type,
 | |
|                          Object result)
 | |
|     throws XPathException, DOMException
 | |
|   {
 | |
|     XPathExpression xpe =
 | |
|       new DomXPathExpression(this, expression, resolver);
 | |
|     return xpe.evaluate(contextNode, type, result);
 | |
|   }
 | |
| 
 | |
| }
 |