domdocument.java

来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· Java 代码 · 共 790 行 · 第 1/2 页

JAVA
790
字号
/* * Copyright (C) 1999-2001 David Brownell *  * This file is part of GNU JAXP, a library. * * GNU JAXP 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 of the License, or * (at your option) any later version. *  * GNU JAXP 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * As a special exception, if you link this library with other files to * produce an executable, this library does not by itself cause the * resulting executable to be covered by the GNU General Public License. * This exception does not however invalidate any other reasons why the * executable file might be covered by the GNU General Public License.  */package gnu.xml.dom;import java.util.Enumeration;import org.w3c.dom.*;import org.w3c.dom.traversal.*;/** * <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  */public class DomDocument extends DomNode    implements Document, DocumentTraversal{    private final DOMImplementation	implementation;    private boolean			checkingCharacters = true;    // package private    final static String			xmlNamespace =	"http://www.w3.org/XML/1998/namespace";    final static String			xmlnsURI =	"http://www.w3.org/2000/xmlns/";    /**     * 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 ()    {	super (null);	implementation = 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 (null);	implementation = impl;    }    /**     * <b>DOM L1</b>     * Returns the constant "#document".     */    final public String getNodeName ()    {	return "#document";    }    /**     * <b>DOM L1</b>     * Returns the constant DOCUMENT_NODE.     */    final public short getNodeType ()	{ return DOCUMENT_NODE; }    /**     * <b>DOM L1</b>     * Returns the document's root element, or null.     */    final public Element getDocumentElement ()    {	for (int i = 0; i < getLength (); i++) {	    Node n = item (i);	    if (n.getNodeType () == ELEMENT_NODE)		return (Element) n;	}	return null;    }    /**     * <b>DOM L1</b>     * Returns the document's DocumentType, or null.     */    final public DocumentType getDoctype ()    {	for (int i = 0; i < getLength (); i++) {	    Node n = item (i);	    if (n.getNodeType () == DOCUMENT_TYPE_NODE)		return (DocumentType) n;	}	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)    {	DomDoctype	doctype = (DomDoctype) getDoctype ();	if (doctype == null || !doctype.hasIds ()		|| id == null || id.length () == 0)	    return 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) {		Element			element = (Element) current;		DomDoctype.ElementInfo	info;		info = doctype.getElementInfo (current.getNodeName ());		if (id.equals (element.getAttribute (info.getIdAttr ())))		    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 DomEx (DomEx.HIERARCHY_REQUEST_ERR, null, newChild, 0);	if (newChild.getNodeType () == DOCUMENT_TYPE_NODE		&& getDoctype () != null)	    throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR, null, 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)    {	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)    {	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 (!(newChild.getNodeType () == ELEMENT_NODE		    && refChild.getNodeType () != ELEMENT_NODE)		&& !(newChild.getNodeType () == DOCUMENT_TYPE_NODE		    && refChild.getNodeType () != ELEMENT_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.  Actually this uses a very similar set of rules, closer to     * Unicode rules than to the rules encoded in the large table at the     * end of the XML 1.0 specification.     *     * @exception DomException INVALID_CHARACTER_ERR if the name isn't     *	legal as an XML name.     */    static public void verifyXmlName (String name)    {	char c;	int len = name.length ();	if (len == 0)	    throw new DomEx (DomEx.NAMESPACE_ERR, name, null, 0);	// NOTE:  these aren't really the XML rules, but they're	// a close approximation that's simple to implement.	c = name.charAt (0);	if (!Character.isUnicodeIdentifierStart (c)		&& c != ':' && c != '_')	    throw new DomEx (DomEx.INVALID_CHARACTER_ERR,		name, null, c);	for (int i = 1; i < len; i++) {	    c = name.charAt (i);	    if (!Character.isUnicodeIdentifierPart (c)		     && c != ':'&& c != '_' && c != '.' && c != '-'		    && !isExtender (c))		throw new DomEx (DomEx.INVALID_CHARACTER_ERR,		    name, null, c);	}    }    static private boolean isExtender (char c)    {	// [88] Extender ::= ...	return c == 0x00b7 || c == 0x02d0 || c == 0x02d1 || c == 0x0387		|| c == 0x0640 || c == 0x0e46 || c == 0x0ec6 || c == 0x3005		|| (c >= 0x3031 && c <= 0x3035)		|| (c >= 0x309d && c <= 0x309e)		|| (c >= 0x30fc && c <= 0x30fe);    }    // package private    static void verifyNamespaceName (String name)    {	int index = name.indexOf (':');	if (index < 0) {	    verifyXmlName (name);	    return;	}	if (name.lastIndexOf (':') != index)	    throw new DomEx (DomEx.NAMESPACE_ERR, name, null, 0);	verifyXmlName (name.substring (0, index));	verifyXmlName (name.substring (index + 1));    }    // package private    static void verifyXmlCharacters (String value)    {	int len = value.length ();	for (int i = 0; i < len; i++) {	    char c = value.charAt (i);	    // assume surrogate pairing checks out OK, for simplicity	    if (c >= 0x0020 && c <= 0xFFFD)		continue;	    if (c == '\n' || c == '\t' || c == '\r')		continue;	    throw new DomEx (DomEx.INVALID_CHARACTER_ERR, value, null, c);	}    }    // package private    static void verifyXmlCharacters (char buf [], int off, int len)    {	for (int i = 0; i < len; i++) {	    char c = buf [off + i];	    // assume surrogate pairing checks out OK, for simplicity	    if (c >= 0x0020 && c <= 0xFFFD)		continue;	    if (c == '\n' || c == '\t' || c == '\r')		continue;	    throw new DomEx (DomEx.INVALID_CHARACTER_ERR,		new String (buf, off, len), null, c);	}    }    /**     * Controls whether certain expensive checks, duplicating those that     * conformant XML parsers must perform, are made.     */    final public void setCheckingCharacters (boolean value)    {	checkingCharacters = value;    }    /**     * Returns true if certain expensive checks are performed.     * Those checks are intended to reject illegal names, and characters     * that are illegal as XML characters.     */    final public boolean isCheckingCharacters ()    {	return checkingCharacters;    }    /**     * <b>DOM L1</b>     * Returns a newly created element with the specified name.     */    public Element createElement (String name)    {	Element		element;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?