summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--luni/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java23
-rw-r--r--luni/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java119
-rw-r--r--luni/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java19
-rw-r--r--luni/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java84
-rw-r--r--luni/src/test/java/tests/xml/DomTest.java54
5 files changed, 183 insertions, 116 deletions
diff --git a/luni/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java b/luni/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java
index fb9821288f..4c682494e3 100644
--- a/luni/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java
@@ -43,35 +43,16 @@ public final class AttrImpl extends NodeImpl implements Attr {
String prefix;
String localName;
- private String value;
+ private String value = "";
AttrImpl(DocumentImpl document, String namespaceURI, String qualifiedName) {
super(document);
-
setNameNS(this, namespaceURI, qualifiedName);
- value = "";
}
AttrImpl(DocumentImpl document, String name) {
super(document);
-
- this.namespaceAware = false;
-
- int prefixSeparator = name.lastIndexOf(":");
- if (prefixSeparator != -1) {
- String prefix = name.substring(0, prefixSeparator);
- String localName = name.substring(prefixSeparator + 1);
-
- if (!DocumentImpl.isXMLIdentifier(prefix) || !DocumentImpl.isXMLIdentifier(localName)) {
- throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
- }
- } else {
- if (!DocumentImpl.isXMLIdentifier(name)) {
- throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
- }
- }
-
- this.localName = name;
+ setName(this, name);
}
@Override
diff --git a/luni/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java b/luni/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
index c5e4054066..75b247fa27 100644
--- a/luni/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
@@ -20,7 +20,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
-import org.w3c.dom.Attr;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMConfiguration;
@@ -129,67 +128,81 @@ public final class DocumentImpl extends InnerNodeImpl implements Document {
*/
private NodeImpl shallowCopy(short operation, Node node) {
switch (node.getNodeType()) {
- case Node.ATTRIBUTE_NODE:
- Attr attr = (Attr) node;
- AttrImpl attrCopy = createAttributeNS(attr.getNamespaceURI(), attr.getLocalName());
+ case Node.ATTRIBUTE_NODE:
+ AttrImpl attr = (AttrImpl) node;
+ AttrImpl attrCopy;
+ if (attr.namespaceAware) {
+ attrCopy = createAttributeNS(attr.getNamespaceURI(), attr.getLocalName());
attrCopy.setPrefix(attr.getPrefix());
- attrCopy.setNodeValue(attr.getNodeValue());
- return attrCopy;
+ } else {
+ attrCopy = createAttribute(attr.getName());
+ }
+ attrCopy.setNodeValue(attr.getValue());
+ return attrCopy;
- case Node.CDATA_SECTION_NODE:
- return createCDATASection(((CharacterData) node).getData());
+ case Node.CDATA_SECTION_NODE:
+ return createCDATASection(((CharacterData) node).getData());
- case Node.COMMENT_NODE:
- return createComment(((Comment) node).getData());
+ case Node.COMMENT_NODE:
+ return createComment(((Comment) node).getData());
- case Node.DOCUMENT_FRAGMENT_NODE:
- return createDocumentFragment();
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ return createDocumentFragment();
- case Node.DOCUMENT_NODE:
- case Node.DOCUMENT_TYPE_NODE:
- throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
- "Cannot copy node of type " + node.getNodeType());
+ case Node.DOCUMENT_NODE:
+ case Node.DOCUMENT_TYPE_NODE:
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
+ "Cannot copy node of type " + node.getNodeType());
- case Node.ELEMENT_NODE:
- Element element = (Element) node;
- ElementImpl elementCopy = createElementNS(
- element.getNamespaceURI(), element.getLocalName());
+ case Node.ELEMENT_NODE:
+ ElementImpl element = (ElementImpl) node;
+ ElementImpl elementCopy;
+ if (element.namespaceAware) {
+ elementCopy = createElementNS(element.getNamespaceURI(), element.getLocalName());
elementCopy.setPrefix(element.getPrefix());
- NamedNodeMap attributes = element.getAttributes();
- for (int i = 0; i < attributes.getLength(); i++) {
- Node elementAttr = attributes.item(i);
- AttrImpl elementAttrCopy = (AttrImpl) shallowCopy(operation, elementAttr);
- notifyUserDataHandlers(operation, elementAttr, elementAttrCopy);
+ } else {
+ elementCopy = createElement(element.getTagName());
+ }
+
+ NamedNodeMap attributes = element.getAttributes();
+ for (int i = 0; i < attributes.getLength(); i++) {
+ AttrImpl elementAttr = (AttrImpl) attributes.item(i);
+ AttrImpl elementAttrCopy = (AttrImpl) shallowCopy(operation, elementAttr);
+ notifyUserDataHandlers(operation, elementAttr, elementAttrCopy);
+ if (elementAttr.namespaceAware) {
elementCopy.setAttributeNodeNS(elementAttrCopy);
+ } else {
+ elementCopy.setAttributeNode(elementAttrCopy);
}
- return elementCopy;
-
- case Node.ENTITY_NODE:
- case Node.NOTATION_NODE:
- // TODO: implement this when we support these node types
- throw new UnsupportedOperationException();
-
- case Node.ENTITY_REFERENCE_NODE:
- /*
- * When we support entities in the doctype, this will need to
- * behave differently for clones vs. imports. Clones copy
- * entities by value, copying the referenced subtree from the
- * original document. Imports copy entities by reference,
- * possibly referring to a different subtree in the new
- * document.
- */
- return createEntityReference(node.getNodeName());
-
- case Node.PROCESSING_INSTRUCTION_NODE:
- ProcessingInstruction pi = (ProcessingInstruction) node;
- return createProcessingInstruction(pi.getTarget(), pi.getData());
-
- case Node.TEXT_NODE:
- return createTextNode(((Text) node).getData());
-
- default:
- throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
- "Unsupported node type " + node.getNodeType());
+ }
+ return elementCopy;
+
+ case Node.ENTITY_NODE:
+ case Node.NOTATION_NODE:
+ // TODO: implement this when we support these node types
+ throw new UnsupportedOperationException();
+
+ case Node.ENTITY_REFERENCE_NODE:
+ /*
+ * When we support entities in the doctype, this will need to
+ * behave differently for clones vs. imports. Clones copy
+ * entities by value, copying the referenced subtree from the
+ * original document. Imports copy entities by reference,
+ * possibly referring to a different subtree in the new
+ * document.
+ */
+ return createEntityReference(node.getNodeName());
+
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ ProcessingInstruction pi = (ProcessingInstruction) node;
+ return createProcessingInstruction(pi.getTarget(), pi.getData());
+
+ case Node.TEXT_NODE:
+ return createTextNode(((Text) node).getData());
+
+ default:
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
+ "Unsupported node type " + node.getNodeType());
}
}
diff --git a/luni/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java b/luni/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java
index eae527c9b8..370100be8c 100644
--- a/luni/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java
@@ -53,24 +53,7 @@ public class ElementImpl extends InnerNodeImpl implements Element {
ElementImpl(DocumentImpl document, String name) {
super(document);
-
- this.namespaceAware = false;
-
- int p = name.lastIndexOf(":");
- if (p != -1) {
- String prefix = name.substring(0, p);
- String localName = name.substring(p + 1);
-
- if (!DocumentImpl.isXMLIdentifier(prefix) || !DocumentImpl.isXMLIdentifier(localName)) {
- throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
- }
- } else {
- if (!DocumentImpl.isXMLIdentifier(name)) {
- throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
- }
- }
-
- this.localName = name;
+ setName(this, name);
}
private int indexOfAttribute(String name) {
diff --git a/luni/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/luni/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java
index 7c26112e8d..647723de08 100644
--- a/luni/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java
@@ -216,10 +216,10 @@ public abstract class NodeImpl implements Node {
}
/**
- * Sets the element or attribute node to be namespace-aware and assign it
- * the specified name and namespace URI.
+ * Sets {@code node} to be namespace-aware and assigns its namespace URI
+ * and qualified name.
*
- * @param node an AttrImpl or ElementImpl node.
+ * @param node an element or attribute node.
* @param namespaceURI this node's namespace URI. May be null.
* @param qualifiedName a possibly-prefixed name like "img" or "html:img".
*/
@@ -240,30 +240,66 @@ public abstract class NodeImpl implements Node {
}
switch (node.getNodeType()) {
- case ATTRIBUTE_NODE:
- if ("xmlns".equals(qualifiedName)
- && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) {
- throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName);
- }
+ case ATTRIBUTE_NODE:
+ if ("xmlns".equals(qualifiedName)
+ && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) {
+ throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName);
+ }
- AttrImpl attr = (AttrImpl) node;
- attr.namespaceAware = true;
- attr.namespaceURI = namespaceURI;
- attr.prefix = prefix;
- attr.localName = qualifiedName;
- break;
+ AttrImpl attr = (AttrImpl) node;
+ attr.namespaceAware = true;
+ attr.namespaceURI = namespaceURI;
+ attr.prefix = prefix;
+ attr.localName = qualifiedName;
+ break;
+
+ case ELEMENT_NODE:
+ ElementImpl element = (ElementImpl) node;
+ element.namespaceAware = true;
+ element.namespaceURI = namespaceURI;
+ element.prefix = prefix;
+ element.localName = qualifiedName;
+ break;
+
+ default:
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
+ "Cannot rename nodes of type " + node.getNodeType());
+ }
+ }
- case ELEMENT_NODE:
- ElementImpl element = (ElementImpl) node;
- element.namespaceAware = true;
- element.namespaceURI = namespaceURI;
- element.prefix = prefix;
- element.localName = qualifiedName;
- break;
+ /**
+ * Sets {@code node} to be not namespace-aware and assigns its name.
+ *
+ * @param node an element or attribute node.
+ */
+ static void setName(NodeImpl node, String name) {
+ int prefixSeparator = name.lastIndexOf(":");
+ if (prefixSeparator != -1) {
+ String prefix = name.substring(0, prefixSeparator);
+ String localName = name.substring(prefixSeparator + 1);
+ if (!DocumentImpl.isXMLIdentifier(prefix) || !DocumentImpl.isXMLIdentifier(localName)) {
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
+ }
+ } else if (!DocumentImpl.isXMLIdentifier(name)) {
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
+ }
- default:
- throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
- "Cannot rename nodes of type " + node.getNodeType());
+ switch (node.getNodeType()) {
+ case ATTRIBUTE_NODE:
+ AttrImpl attr = (AttrImpl) node;
+ attr.namespaceAware = false;
+ attr.localName = name;
+ break;
+
+ case ELEMENT_NODE:
+ ElementImpl element = (ElementImpl) node;
+ element.namespaceAware = false;
+ element.localName = name;
+ break;
+
+ default:
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
+ "Cannot rename nodes of type " + node.getNodeType());
}
}
diff --git a/luni/src/test/java/tests/xml/DomTest.java b/luni/src/test/java/tests/xml/DomTest.java
index 8477676d0f..3f68d7c5be 100644
--- a/luni/src/test/java/tests/xml/DomTest.java
+++ b/luni/src/test/java/tests/xml/DomTest.java
@@ -805,6 +805,60 @@ public class DomTest extends TestCase {
}
}
+ public void testValueOfNewAttributesIsEmptyString() {
+ assertEquals("", document.createAttribute("bar").getValue());
+ assertEquals("", document.createAttributeNS("http://foo", "bar").getValue());
+ }
+
+ public void testCloneNode() throws Exception {
+ document = builder.parse(new InputSource(new StringReader("<menu "
+ + "xmlns:f=\"http://food\" xmlns:a=\"http://addons\">"
+ + "<f:item a:standard=\"strawberry\" deluxe=\"yes\">Waffles</f:item></menu>")));
+ name = (Element) document.getFirstChild().getFirstChild();
+
+ Element clonedName = (Element) name.cloneNode(true);
+ assertNull(clonedName.getParentNode());
+ assertNull(clonedName.getNextSibling());
+ assertNull(clonedName.getPreviousSibling());
+ assertEquals("http://food", clonedName.getNamespaceURI());
+ assertEquals("f:item", clonedName.getNodeName());
+ assertEquals("item", clonedName.getLocalName());
+ assertEquals("http://food", clonedName.getNamespaceURI());
+ assertEquals("yes", clonedName.getAttribute("deluxe"));
+ assertEquals("strawberry", clonedName.getAttribute("a:standard"));
+ assertEquals("strawberry", clonedName.getAttributeNS("http://addons", "standard"));
+ assertEquals(1, name.getChildNodes().getLength());
+
+ Text clonedChild = (Text) clonedName.getFirstChild();
+ assertSame(clonedName, clonedChild.getParentNode());
+ assertNull(clonedChild.getNextSibling());
+ assertNull(clonedChild.getPreviousSibling());
+ assertEquals("Waffles", clonedChild.getTextContent());
+ }
+
+ /**
+ * We can't use the namespace-aware factory method for non-namespace-aware
+ * nodes. http://code.google.com/p/android/issues/detail?id=2735
+ */
+ public void testCloneNodeNotNamespaceAware() throws Exception {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(false);
+ builder = factory.newDocumentBuilder();
+ document = builder.parse(new InputSource(new StringReader("<menu "
+ + "xmlns:f=\"http://food\" xmlns:a=\"http://addons\">"
+ + "<f:item a:standard=\"strawberry\" deluxe=\"yes\">Waffles</f:item></menu>")));
+ name = (Element) document.getFirstChild().getFirstChild();
+
+ Element clonedName = (Element) name.cloneNode(true);
+ assertNull(clonedName.getNamespaceURI());
+ assertEquals("f:item", clonedName.getNodeName());
+ assertNull(clonedName.getLocalName());
+ assertNull(clonedName.getNamespaceURI());
+ assertEquals("yes", clonedName.getAttribute("deluxe"));
+ assertEquals("strawberry", clonedName.getAttribute("a:standard"));
+ assertEquals("", clonedName.getAttributeNS("http://addons", "standard"));
+ }
+
/**
* A shallow clone requires cloning the attributes but not the child nodes.
*/