| /* 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; | |
| 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; | |
| } | |
| /** | |
| * <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. | |
| */ | |
| 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); | |
| domElement.localName = null; | |
| element = domElement; | |
| } | |
| defaultAttributes(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); | |
| defaultAttributes(element, name); | |
| return element; | |
| } | |
| private void defaultAttributes(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(); | |
| DomAttr node = (DomAttr) createAttribute(attr.name); | |
| String value = attr.value; | |
| 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); | |
| ret.localName = 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); | |
| } | |
| } | |