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);
 | 
						|
  }
 | 
						|
 | 
						|
}
 |