domnodepointer.java
来自「JXPath」· Java 代码 · 共 786 行 · 第 1/2 页
JAVA
786 行
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.jxpath.ri.model.dom;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.jxpath.AbstractFactory;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathException;
import org.apache.commons.jxpath.Pointer;
import org.apache.commons.jxpath.ri.Compiler;
import org.apache.commons.jxpath.ri.QName;
import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
import org.apache.commons.jxpath.ri.compiler.NodeTest;
import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
import org.apache.commons.jxpath.ri.compiler.ProcessingInstructionTest;
import org.apache.commons.jxpath.ri.model.beans.NullPointer;
import org.apache.commons.jxpath.ri.model.NodeIterator;
import org.apache.commons.jxpath.ri.model.NodePointer;
import org.apache.commons.jxpath.util.TypeUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
/**
* A Pointer that points to a DOM node.
*
* @author Dmitri Plotnikov
* @version $Revision: 1.24 $ $Date: 2004/06/29 22:58:17 $
*/
public class DOMNodePointer extends NodePointer {
private Node node;
private Map namespaces;
private String defaultNamespace;
private String id;
public static final String XML_NAMESPACE_URI =
"http://www.w3.org/XML/1998/namespace";
public static final String XMLNS_NAMESPACE_URI =
"http://www.w3.org/2000/xmlns/";
public DOMNodePointer(Node node, Locale locale) {
super(null, locale);
this.node = node;
}
public DOMNodePointer(Node node, Locale locale, String id) {
super(null, locale);
this.node = node;
this.id = id;
}
public DOMNodePointer(NodePointer parent, Node node) {
super(parent);
this.node = node;
}
public boolean testNode(NodeTest test) {
return testNode(node, test);
}
public static boolean testNode(Node node, NodeTest test) {
if (test == null) {
return true;
}
else if (test instanceof NodeNameTest) {
if (node.getNodeType() != Node.ELEMENT_NODE) {
return false;
}
NodeNameTest nodeNameTest = (NodeNameTest) test;
QName testName = nodeNameTest.getNodeName();
String namespaceURI = nodeNameTest.getNamespaceURI();
boolean wildcard = nodeNameTest.isWildcard();
String testPrefix = testName.getPrefix();
if (wildcard && testPrefix == null) {
return true;
}
if (wildcard
|| testName.getName()
.equals(DOMNodePointer.getLocalName(node))) {
String nodeNS = DOMNodePointer.getNamespaceURI(node);
return equalStrings(namespaceURI, nodeNS);
}
}
else if (test instanceof NodeTypeTest) {
int nodeType = node.getNodeType();
switch (((NodeTypeTest) test).getNodeType()) {
case Compiler.NODE_TYPE_NODE :
return nodeType == Node.ELEMENT_NODE;
case Compiler.NODE_TYPE_TEXT :
return nodeType == Node.CDATA_SECTION_NODE
|| nodeType == Node.TEXT_NODE;
case Compiler.NODE_TYPE_COMMENT :
return nodeType == Node.COMMENT_NODE;
case Compiler.NODE_TYPE_PI :
return nodeType == Node.PROCESSING_INSTRUCTION_NODE;
}
return false;
}
else if (test instanceof ProcessingInstructionTest) {
if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
String testPI = ((ProcessingInstructionTest) test).getTarget();
String nodePI = ((ProcessingInstruction) node).getTarget();
return testPI.equals(nodePI);
}
}
return false;
}
private static boolean equalStrings(String s1, String s2) {
if (s1 == null && s2 != null) {
return false;
}
if (s1 != null && s2 == null) {
return false;
}
if (s1 != null && !s1.trim().equals(s2.trim())) {
return false;
}
return true;
}
public QName getName() {
String ln = null;
String ns = null;
int type = node.getNodeType();
if (type == Node.ELEMENT_NODE) {
ns = DOMNodePointer.getPrefix(node);
ln = DOMNodePointer.getLocalName(node);
}
else if (type == Node.PROCESSING_INSTRUCTION_NODE) {
ln = ((ProcessingInstruction) node).getTarget();
}
return new QName(ns, ln);
}
public String getNamespaceURI() {
return getNamespaceURI(node);
}
public NodeIterator childIterator(
NodeTest test,
boolean reverse,
NodePointer startWith)
{
return new DOMNodeIterator(this, test, reverse, startWith);
}
public NodeIterator attributeIterator(QName name) {
return new DOMAttributeIterator(this, name);
}
public NodePointer namespacePointer(String prefix) {
return new NamespacePointer(this, prefix);
}
public NodeIterator namespaceIterator() {
return new DOMNamespaceIterator(this);
}
public String getNamespaceURI(String prefix) {
if (prefix == null || prefix.equals("")) {
return getDefaultNamespaceURI();
}
if (prefix.equals("xml")) {
return XML_NAMESPACE_URI;
}
if (prefix.equals("xmlns")) {
return XMLNS_NAMESPACE_URI;
}
String namespace = null;
if (namespaces == null) {
namespaces = new HashMap();
}
else {
namespace = (String) namespaces.get(prefix);
}
if (namespace == null) {
String qname = "xmlns:" + prefix;
Node aNode = node;
if (aNode instanceof Document) {
aNode = ((Document)aNode).getDocumentElement();
}
while (aNode != null) {
if (aNode.getNodeType() == Node.ELEMENT_NODE) {
Attr attr = ((Element) aNode).getAttributeNode(qname);
if (attr != null) {
namespace = attr.getValue();
break;
}
}
aNode = aNode.getParentNode();
}
if (namespace == null || namespace.equals("")) {
namespace = NodePointer.UNKNOWN_NAMESPACE;
}
}
namespaces.put(prefix, namespace);
// TBD: We are supposed to resolve relative URIs to absolute ones.
return namespace;
}
private String getNamespaceURI(String prefix, String namespace) {
String qname = "xmlns:" + prefix;
Node aNode = node;
if (aNode instanceof Document) {
aNode = ((Document)aNode).getDocumentElement();
}
while (aNode != null) {
if (aNode.getNodeType() == Node.ELEMENT_NODE) {
Attr attr = ((Element) aNode).getAttributeNode(qname);
if (attr != null) {
namespace = attr.getValue();
break;
}
}
aNode = aNode.getParentNode();
}
return namespace;
}
public String getDefaultNamespaceURI() {
if (defaultNamespace == null) {
Node aNode = node;
while (aNode != null) {
if (aNode.getNodeType() == Node.ELEMENT_NODE) {
Attr attr = ((Element) aNode).getAttributeNode("xmlns");
if (attr != null) {
defaultNamespace = attr.getValue();
break;
}
}
aNode = aNode.getParentNode();
}
}
if (defaultNamespace == null) {
defaultNamespace = "";
}
// TBD: We are supposed to resolve relative URIs to absolute ones.
return defaultNamespace.equals("") ? null : defaultNamespace;
}
public Object getBaseValue() {
return node;
}
public Object getImmediateNode() {
return node;
}
public boolean isActual() {
return true;
}
public boolean isCollection() {
return false;
}
public int getLength() {
return 1;
}
public boolean isLeaf() {
return !node.hasChildNodes();
}
/**
* Returns true if the xml:lang attribute for the current node
* or its parent has the specified prefix <i>lang</i>.
* If no node has this prefix, calls <code>super.isLanguage(lang)</code>.
*/
public boolean isLanguage(String lang) {
String current = getLanguage();
if (current == null) {
return super.isLanguage(lang);
}
return current.toUpperCase().startsWith(lang.toUpperCase());
}
protected String getLanguage() {
Node n = node;
while (n != null) {
if (n.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) n;
String attr = e.getAttribute("xml:lang");
if (attr != null && !attr.equals("")) {
return attr;
}
}
n = n.getParentNode();
}
return null;
}
/**
* Sets contents of the node to the specified value. If the value is
* a String, the contents of the node are replaced with this text.
* If the value is an Element or Document, the children of the
* node are replaced with the children of the passed node.
*/
public void setValue(Object value) {
if (node.getNodeType() == Node.TEXT_NODE
|| node.getNodeType() == Node.CDATA_SECTION_NODE) {
String string = (String) TypeUtils.convert(value, String.class);
if (string != null && !string.equals("")) {
node.setNodeValue(string);
}
else {
node.getParentNode().removeChild(node);
}
}
else {
NodeList children = node.getChildNodes();
int count = children.getLength();
for (int i = count; --i >= 0;) {
Node child = children.item(i);
node.removeChild(child);
}
if (value instanceof Node) {
Node valueNode = (Node) value;
if (valueNode instanceof Element
|| valueNode instanceof Document) {
children = valueNode.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
node.appendChild(child.cloneNode(true));
}
}
else {
node.appendChild(valueNode.cloneNode(true));
}
}
else {
String string = (String) TypeUtils.convert(value, String.class);
if (string != null && !string.equals("")) {
Node textNode =
node.getOwnerDocument().createTextNode(string);
node.appendChild(textNode);
}
}
}
}
public NodePointer createChild(
JXPathContext context,
QName name,
int index)
{
if (index == WHOLE_COLLECTION) {
index = 0;
}
boolean success =
getAbstractFactory(context).createObject(
context,
this,
node,
name.toString(),
index);
if (success) {
NodeTest nodeTest;
String prefix = name.getPrefix();
if (prefix != null) {
String namespaceURI = context.getNamespaceURI(prefix);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?