From 2e4c40c282464cb5435b3078b8d375634355dbc1 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Tue, 2 Feb 2010 11:39:05 -0800 Subject: Fixing some of our XSLT implementation issues. These changes move our XSLT code to passing 1898/3173 of the OASIS tests. To contrast, the RI passes 2105/3173 tests. Highlights: - Implementing getTextContent() for nodes - Removing validation during transforms. We don't support validation! - Fixing attribute constraints to match the spec - Fixing test suite to not confuse BaseURI from NamespaceURI --- .../java/org/apache/harmony/xml/dom/AttrImpl.java | 11 ++++---- .../org/apache/harmony/xml/dom/DocumentImpl.java | 4 +++ .../apache/harmony/xml/dom/DocumentTypeImpl.java | 3 ++ .../org/apache/harmony/xml/dom/InnerNodeImpl.java | 31 ++++++++++++++++++++ .../java/org/apache/harmony/xml/dom/NodeImpl.java | 11 ++++++-- .../main/java/org/apache/xml/utils/DOMHelper.java | 27 +++++++++++------- .../harmony/xml/XsltXPathConformanceTestSuite.java | 33 +++++++++++++--------- 7 files changed, 90 insertions(+), 30 deletions(-) (limited to 'xml/src') diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java index 9c19835..59a8b78 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java @@ -159,11 +159,12 @@ public class AttrImpl extends NodeImpl implements Attr { } if (prefix != null) { - if (namespaceURI == null || !document.isXMLIdentifier(prefix) || "xmlns".equals(prefix)) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - - if ("xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI)) { + if (namespaceURI == null + || !DocumentImpl.isXMLIdentifier(prefix) + || ("xmlns".equals(prefix) + && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) + || ("xml".equals(prefix) + && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI))) { throw new DOMException(DOMException.NAMESPACE_ERR, prefix); } } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java index 499f518..d6d412b 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java @@ -296,6 +296,10 @@ public class DocumentImpl extends InnerNodeImpl implements Document { return super.insertChildAt(newChild, index); } + @Override public String getTextContent() throws DOMException { + return null; + } + public String getInputEncoding() { throw new UnsupportedOperationException(); // TODO } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java index df40d4b..67947b7 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java @@ -107,4 +107,7 @@ public class DocumentTypeImpl extends LeafNodeImpl implements DocumentType { return systemId; } + @Override public String getTextContent() throws DOMException { + return null; + } } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java index f8ed85e..82cd25e 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java @@ -218,4 +218,35 @@ public abstract class InnerNodeImpl extends LeafNodeImpl { return oldChildImpl; } + public String getTextContent() throws DOMException { + Node child = getFirstChild(); + if (child == null) { + return ""; + } + + Node next = child.getNextSibling(); + if (next == null) { + return hasTextContent(child) ? child.getTextContent() : ""; + } + + StringBuilder buf = new StringBuilder(); + getTextContent(buf); + return buf.toString(); + } + + void getTextContent(StringBuilder buf) throws DOMException { + Node child = getFirstChild(); + while (child != null) { + if (hasTextContent(child)) { + ((NodeImpl) child).getTextContent(buf); + } + child = child.getNextSibling(); + } + } + + final boolean hasTextContent(Node child) { + // TODO: skip text nodes with ignorable whitespace? + return child.getNodeType() != Node.COMMENT_NODE + && child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE; + } } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java index bf4d791..b752506 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java @@ -190,7 +190,7 @@ public abstract class NodeImpl implements Node { } public String getBaseURI() { - throw new UnsupportedOperationException(); // TODO + return null; // TODO } public short compareDocumentPosition(Node other) @@ -199,7 +199,14 @@ public abstract class NodeImpl implements Node { } public String getTextContent() throws DOMException { - throw new UnsupportedOperationException(); // TODO + return getNodeValue(); + } + + void getTextContent(StringBuilder buf) throws DOMException { + String content = getNodeValue(); + if (content != null) { + buf.append(content); + } } public void setTextContent(String textContent) throws DOMException { diff --git a/xml/src/main/java/org/apache/xml/utils/DOMHelper.java b/xml/src/main/java/org/apache/xml/utils/DOMHelper.java index 76721d0..53d0adc 100644 --- a/xml/src/main/java/org/apache/xml/utils/DOMHelper.java +++ b/xml/src/main/java/org/apache/xml/utils/DOMHelper.java @@ -85,16 +85,23 @@ public class DOMHelper DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); dfactory.setNamespaceAware(true); - dfactory.setValidating(true); - - if (isSecureProcessing) - { - try - { - dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - } - catch (ParserConfigurationException pce) {} - } + // BEGIN android-removed + // If set, DocumentBuilderFactoryImpl.newDocumentBuilder() fails + // because we haven't implemented validation + // dfactory.setValidating(true); + // BEGIN android-removed + + // BEGIN android-removed + // We haven't implemented secure processing + // if (isSecureProcessing) + // { + // try + // { + // dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + // } + // catch (ParserConfigurationException pce) {} + // } + // END android-removed DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); Document outNode = docBuilder.newDocument(); diff --git a/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java b/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java index 7773814..443e415 100644 --- a/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java +++ b/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java @@ -78,7 +78,7 @@ public class XsltXPathConformanceTestSuite { /** Orders element attributes by optional URI and name. */ private static final Comparator orderByName = new Comparator() { public int compare(Attr a, Attr b) { - int result = compareNullsFirst(a.getBaseURI(), b.getBaseURI()); + int result = compareNullsFirst(a.getNamespaceURI(), b.getNamespaceURI()); return result == 0 ? result : compareNullsFirst(a.getName(), b.getName()); } @@ -322,6 +322,11 @@ public class XsltXPathConformanceTestSuite { this.compareAs = compareAs; } + XsltTest(File principalData, File principalStylesheet, File principal) { + this("standalone", "test", "", "", + principalData, principalStylesheet, principal, "standard", "XML"); + } + public void test() throws Exception { if (purpose != null) { System.out.println("Purpose: " + purpose); @@ -336,8 +341,8 @@ public class XsltXPathConformanceTestSuite { Transformer transformer; try { transformer = transformerFactory.newTransformer(xslt); - assertEquals("Expected transformer creation to fail", - "standard", operation); + assertEquals("Transformer creation completed normally.", + operation, "standard"); } catch (TransformerConfigurationException e) { if (operation.equals("execution-error")) { return; // expected, such as in XSLT-Result-Tree.Attributes__78369 @@ -396,14 +401,17 @@ public class XsltXPathConformanceTestSuite { } private void emitNode(XmlSerializer serializer, Node node) throws IOException { - if (node instanceof Element) { + if (node == null) { + throw new UnsupportedOperationException("Cannot emit null nodes"); + + } else if (node.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) node; - serializer.startTag(element.getBaseURI(), element.getLocalName()); + serializer.startTag(element.getNamespaceURI(), element.getLocalName()); emitAttributes(serializer, element); emitChildren(serializer, element); - serializer.endTag(element.getBaseURI(), element.getLocalName()); + serializer.endTag(element.getNamespaceURI(), element.getLocalName()); - } else if (node instanceof Text) { + } else if (node.getNodeType() == Node.TEXT_NODE) { // TODO: is it okay to trim whitespace in general? This may cause // false positives for elements like HTML's
 tag
             String trimmed = node.getTextContent().trim();
@@ -411,25 +419,24 @@ public class XsltXPathConformanceTestSuite {
                 serializer.text(trimmed);
             }
 
-        } else if (node instanceof Document) {
+        } else if (node.getNodeType() == Node.DOCUMENT_NODE) {
             Document document = (Document) node;
             serializer.startDocument("UTF-8", true);
             emitNode(serializer, document.getDocumentElement());
             serializer.endDocument();
 
-        } else if (node instanceof ProcessingInstruction) {
+        } else if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
             ProcessingInstruction processingInstruction = (ProcessingInstruction) node;
             String data = processingInstruction.getData();
             String target = processingInstruction.getTarget();
             serializer.processingInstruction(target + " " + data);
 
-        } else if (node instanceof Comment) {
+        } else if (node.getNodeType() == Node.COMMENT_NODE) {
             // ignore!
 
         } else {
-            Object nodeClass = node != null ? node.getClass() : null;
             throw new UnsupportedOperationException(
-                    "Cannot serialize nodes of type " + nodeClass);
+                    "Cannot emit " + node + " of type " + node.getNodeType());
         }
     }
 
@@ -458,7 +465,7 @@ public class XsltXPathConformanceTestSuite {
                  * generate one for us, using a predictable pattern.
                  */
             } else {
-                serializer.attribute(attr.getBaseURI(), attr.getLocalName(), attr.getValue());
+                serializer.attribute(attr.getNamespaceURI(), attr.getLocalName(), attr.getValue());
             }
         }
     }
-- 
cgit v1.1


From 2f4bbf1068869f45783608450731f83c523ded30 Mon Sep 17 00:00:00 2001
From: Jesse Wilson 
Date: Thu, 11 Feb 2010 12:40:50 -0800
Subject: Fixing problems with the test runner's ability to parse expected
 results files.

It appears that the original authors of this testing framework didn't really
know whether these files were supposed to be XML or HTML, UTF-8 or UTF-16, and
so there's quite a mess of processing in order to canonicalize them.
---
 .../org/apache/harmony/xml/dom/InnerNodeImpl.java  |  18 +-
 .../xalan/processor/TransformerFactoryImpl.java    |   2 +-
 .../harmony/xml/XsltXPathConformanceTestSuite.java | 213 +++++++++++++++++----
 3 files changed, 190 insertions(+), 43 deletions(-)

(limited to 'xml/src')

diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
index 82cd25e..275bbf3 100644
--- a/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
@@ -28,14 +28,16 @@ import java.util.List;
  * Provides a straightforward implementation of the corresponding W3C DOM
  * interface. The class is used internally only, thus only notable members that
  * are not in the original interface are documented (the W3C docs are quite
- * extensive). Hope that's ok.
- * 

- * Some of the fields may have package visibility, so other classes belonging to - * the DOM implementation can easily access them while maintaining the DOM tree - * structure. - *

- * This class represents a Node that has a parent Node as well as (potentially) - * a number of children. + * extensive). + * + *

Some of the fields may have package visibility, so other classes belonging + * to the DOM implementation can easily access them while maintaining the DOM + * tree structure. + * + *

This class represents a Node that has a parent Node as well as + * (potentially) a number of children. + * + *

Some code was adapted from Apache Xerces. */ public abstract class InnerNodeImpl extends LeafNodeImpl { diff --git a/xml/src/main/java/org/apache/xalan/processor/TransformerFactoryImpl.java b/xml/src/main/java/org/apache/xalan/processor/TransformerFactoryImpl.java index 78d0cc5..618b412 100644 --- a/xml/src/main/java/org/apache/xalan/processor/TransformerFactoryImpl.java +++ b/xml/src/main/java/org/apache/xalan/processor/TransformerFactoryImpl.java @@ -792,7 +792,7 @@ public class TransformerFactoryImpl extends SAXTransformerFactory try { m_errorListener.fatalError( ex ); - return null; + return null; // TODO: but the API promises to never return null... } catch( TransformerConfigurationException ex1 ) { diff --git a/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java b/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java index 443e415..7dbfaea 100644 --- a/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java +++ b/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java @@ -23,15 +23,16 @@ import junit.framework.TestCase; import junit.framework.TestSuite; import junit.textui.TestRunner; import org.w3c.dom.Attr; -import org.w3c.dom.Comment; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.EntityReference; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.ProcessingInstruction; -import org.w3c.dom.Text; +import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import org.xmlpull.v1.XmlSerializer; @@ -39,17 +40,25 @@ import org.xmlpull.v1.XmlSerializer; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.ErrorListener; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collections; @@ -61,13 +70,23 @@ import java.util.List; * XSLT conformance test suite, adapted for use by JUnit. To run these tests * on a device: *

+ * + *

Unfortunately, some of the tests in the OASIS suite will fail when + * executed outside of their original development environment: + *

    + *
  • The tests assume case insensitive filesystems. Some will fail with + * "Couldn't open file" errors due to a mismatch in file name casing. + *
  • The tests assume certain network hosts will exist and serve + * stylesheet files. In particular, "http://webxtest/" isn't generally + * available. *
*/ public class XsltXPathConformanceTestSuite { @@ -164,7 +183,7 @@ public class XsltXPathConformanceTestSuite { /** * Returns a JUnit test for the test described by the given element. */ - private Test create(File base, Element testCaseElement) { + private TestCase create(File base, Element testCaseElement) { /* * Extract the XSLT test from a DOM entity with the following structure: @@ -291,7 +310,6 @@ public class XsltXPathConformanceTestSuite { * the result to an expected output file. */ public class XsltTest extends TestCase { - // TODO: include these in toString private final String category; private final String id; private final String purpose; @@ -304,7 +322,10 @@ public class XsltXPathConformanceTestSuite { /** either "standard" or "execution-error" */ private final String operation; - /** the syntax to compare the output file using, such as "XML" or "HTML" */ + /** + * The syntax to compare the output file using, such as "XML", "HTML", + * "manual", or null for expected execution errors. + */ private final String compareAs; XsltTest(String category, String id, String purpose, String spec, @@ -335,37 +356,50 @@ public class XsltXPathConformanceTestSuite { System.out.println("Spec: " + spec); } - Source xslt = new StreamSource(principalStylesheet); - Source in = new StreamSource(principalData); + Result result; + if ("XML".equals(compareAs)) { + DOMResult domResult = new DOMResult(); + domResult.setNode(documentBuilder.newDocument().createElementNS("", "result")); + result = domResult; + } else { + result = new StreamResult(new StringWriter()); + } + + ErrorRecorder errorRecorder = new ErrorRecorder(); + transformerFactory.setErrorListener(errorRecorder); Transformer transformer; try { + Source xslt = new StreamSource(principalStylesheet); transformer = transformerFactory.newTransformer(xslt); - assertEquals("Transformer creation completed normally.", - operation, "standard"); + if (errorRecorder.error == null) { + transformer.setErrorListener(errorRecorder); + transformer.transform(new StreamSource(principalData), result); + } } catch (TransformerConfigurationException e) { - if (operation.equals("execution-error")) { - return; // expected, such as in XSLT-Result-Tree.Attributes__78369 + errorRecorder.fatalError(e); + } + + if (operation.equals("standard")) { + if (errorRecorder.error != null) { + throw errorRecorder.error; + } + } else if (operation.equals("execution-error")) { + if (errorRecorder.error != null) { + return; } - AssertionFailedError failure = new AssertionFailedError(); - failure.initCause(e); - throw failure; + fail("Expected " + operation + ", but transform completed normally." + + " (Warning=" + errorRecorder.warning + ")"); + } else { + throw new UnsupportedOperationException("Unexpected operation: " + operation); } - Result result; - if (compareAs.equals("XML")) { - result = new DOMResult(); + if ("XML".equals(compareAs)) { + assertNodesAreEquivalent(principal, ((DOMResult) result).getNode()); } else { // TODO: implement support for comparing HTML etc. throw new UnsupportedOperationException("Cannot compare as " + compareAs); } - - transformer.transform(in, result); - - if (compareAs.equals("XML")) { - DOMResult domResult = (DOMResult) result; - assertNodesAreEquivalent(principal, domResult.getNode()); - } } @Override public String getName() { @@ -376,19 +410,65 @@ public class XsltXPathConformanceTestSuite { /** * Ensures both XML documents represent the same semantic data. Non-semantic * data such as namespace prefixes, comments, and whitespace is ignored. + * + * @param actual an XML document whose root is a {@code } element. + * @param expected a file containing an XML document fragment. */ private void assertNodesAreEquivalent(File expected, Node actual) throws ParserConfigurationException, IOException, SAXException, XmlPullParserException { - Document expectedDocument = documentBuilder.parse(new FileInputStream(expected)); - String expectedString = nodeToNormalizedString(expectedDocument); + Node expectedNode = fileToResultNode(expected); + String expectedString = nodeToNormalizedString(expectedNode); String actualString = nodeToNormalizedString(actual); Assert.assertEquals("Expected XML to match file " + expected, expectedString, actualString); } + /** + * Returns the given file's XML fragment as a single node, wrapped in + * {@code } tags. This takes care of normalizing the following + * conditions: + * + *
    + *
  • Files containing XML document fragments with multiple elements: + * {@code Smurfs!
    } + * + *
  • Files containing XML document fragments with no elements: + * {@code Smurfs!} + * + *
  • Files containing proper XML documents with a single element and an + * XML declaration: + * {@code } + * + *
  • Files prefixed with a byte order mark header, such as 0xEFBBBF. + *
+ */ + private Node fileToResultNode(File file) throws IOException, SAXException { + String rawContents = fileToString(file); + String fragment = rawContents; + + // If the file had an XML declaration, strip that. Otherwise wrapping + // it in tags would result in a malformed XML document. + if (fragment.startsWith(""); + fragment = fragment.substring(declarationEnd + 2); + } + + // Parse it as document fragment wrapped in tags. + try { + fragment = "" + fragment + ""; + return documentBuilder.parse(new InputSource(new StringReader(fragment))) + .getDocumentElement(); + } catch (SAXParseException e) { + Error error = new AssertionFailedError( + "Failed to parse XML: " + file + "\n" + rawContents); + error.initCause(e); + throw error; + } + } + private String nodeToNormalizedString(Node node) throws XmlPullParserException, IOException { StringWriter writer = new StringWriter(); @@ -411,7 +491,8 @@ public class XsltXPathConformanceTestSuite { emitChildren(serializer, element); serializer.endTag(element.getNamespaceURI(), element.getLocalName()); - } else if (node.getNodeType() == Node.TEXT_NODE) { + } else if (node.getNodeType() == Node.TEXT_NODE + || node.getNodeType() == Node.CDATA_SECTION_NODE) { // TODO: is it okay to trim whitespace in general? This may cause // false positives for elements like HTML's
 tag
             String trimmed = node.getTextContent().trim();
@@ -434,6 +515,10 @@ public class XsltXPathConformanceTestSuite {
         } else if (node.getNodeType() == Node.COMMENT_NODE) {
             // ignore!
 
+        } else if (node.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+            EntityReference entityReference = (EntityReference) node;
+            serializer.entityRef(entityReference.getNodeName());
+
         } else {
             throw new UnsupportedOperationException(
                     "Cannot emit " + node + " of type " + node.getNodeType());
@@ -488,4 +573,64 @@ public class XsltXPathConformanceTestSuite {
         }
         return result;
     }
+
+    /**
+     * Reads the given file into a string. If the file contains a byte order
+     * mark, the corresponding character set will be used. Otherwise the system
+     * default charset will be used.
+     */
+    private String fileToString(File file) throws IOException {
+        InputStream in = new BufferedInputStream(new FileInputStream(file), 1024);
+
+        // Read the byte order mark to determine the charset.
+        // TODO: use a built-in API for this...
+        Reader reader;
+        in.mark(3);
+        int byte1 = in.read();
+        int byte2 = in.read();
+        if (byte1 == 0xFF && byte2 == 0xFE) {
+            reader = new InputStreamReader(in, "UTF-16LE");
+        } else if (byte1 == 0xFF && byte2 == 0xFF) {
+            reader = new InputStreamReader(in, "UTF-16BE");
+        } else {
+            int byte3 = in.read();
+            if (byte1 == 0xEF && byte2 == 0xBB && byte3 == 0xBF) {
+                reader = new InputStreamReader(in, "UTF-8");
+            } else {
+                in.reset();
+                reader = new InputStreamReader(in);
+            }
+        }
+
+        StringWriter out = new StringWriter();
+        char[] buffer = new char[1024];
+        int count;
+        while ((count = reader.read(buffer)) != -1) {
+            out.write(buffer, 0, count);
+        }
+        return out.toString();
+    }
+
+    static class ErrorRecorder implements ErrorListener {
+        Exception warning;
+        Exception error;
+
+        public void warning(TransformerException exception) {
+            if (this.warning == null) {
+                this.warning = exception;
+            }
+        }
+
+        public void error(TransformerException exception) {
+            if (this.error == null) {
+                this.error = exception;
+            }
+        }
+
+        public void fatalError(TransformerException exception) {
+            if (this.error == null) {
+                this.error = exception;
+            }
+        }
+    }
 }
-- 
cgit v1.1


From 0233201f5e7de490d3830ca96e8a18765797ea3a Mon Sep 17 00:00:00 2001
From: Jesse Wilson 
Date: Thu, 11 Feb 2010 16:08:33 -0800
Subject: Removing unnecessary org.w3c.dom subpackages

---
 .../java/org/w3c/dom/events/DocumentEvent.java     |  56 -------
 xml/src/main/java/org/w3c/dom/events/Event.java    | 141 ----------------
 .../java/org/w3c/dom/events/EventException.java    |  36 -----
 .../java/org/w3c/dom/events/EventListener.java     |  41 -----
 .../main/java/org/w3c/dom/events/EventTarget.java  | 102 ------------
 .../main/java/org/w3c/dom/events/MouseEvent.java   | 156 ------------------
 .../java/org/w3c/dom/events/MutationEvent.java     | 108 -------------
 xml/src/main/java/org/w3c/dom/events/UIEvent.java  |  58 -------
 xml/src/main/java/org/w3c/dom/ls/LSLoadEvent.java  |  35 ----
 .../main/java/org/w3c/dom/ls/LSProgressEvent.java  |  48 ------
 xml/src/main/java/org/w3c/dom/ls/LSSerializer.java |   8 +-
 .../java/org/w3c/dom/ls/LSSerializerFilter.java    |   2 +
 .../org/w3c/dom/traversal/DocumentTraversal.java   |  93 -----------
 .../java/org/w3c/dom/traversal/NodeFilter.java     |   2 +
 .../java/org/w3c/dom/traversal/NodeIterator.java   |   2 +
 .../java/org/w3c/dom/traversal/TreeWalker.java     | 179 ---------------------
 .../main/java/org/w3c/dom/views/AbstractView.java  |  27 ----
 .../main/java/org/w3c/dom/views/DocumentView.java  |  30 ----
 18 files changed, 12 insertions(+), 1112 deletions(-)
 delete mode 100644 xml/src/main/java/org/w3c/dom/events/DocumentEvent.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/events/Event.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/events/EventException.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/events/EventListener.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/events/EventTarget.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/events/MouseEvent.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/events/MutationEvent.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/events/UIEvent.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/ls/LSLoadEvent.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/ls/LSProgressEvent.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/traversal/DocumentTraversal.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/traversal/TreeWalker.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/views/AbstractView.java
 delete mode 100644 xml/src/main/java/org/w3c/dom/views/DocumentView.java

(limited to 'xml/src')

diff --git a/xml/src/main/java/org/w3c/dom/events/DocumentEvent.java b/xml/src/main/java/org/w3c/dom/events/DocumentEvent.java
deleted file mode 100644
index 76644bc..0000000
--- a/xml/src/main/java/org/w3c/dom/events/DocumentEvent.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2000 World Wide Web Consortium,
- * (Massachusetts Institute of Technology, Institut National de
- * Recherche en Informatique et en Automatique, Keio University). All
- * Rights Reserved. This program is distributed under the W3C's Software
- * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details.
- */
-
-package org.w3c.dom.events;
-
-import org.w3c.dom.DOMException;
-
-/**
- *  The DocumentEvent interface provides a mechanism by which the 
- * user can create an Event of a type supported by the implementation. It is 
- * expected that the DocumentEvent interface will be 
- * implemented on the same object which implements the Document 
- * interface in an implementation which supports the Event model. 
- * 

See also the Document Object Model (DOM) Level 2 Events Specification. - * @since DOM Level 2 - */ -public interface DocumentEvent { - /** - * - * @param eventType The eventType parameter specifies the - * type of Event interface to be created. If the - * Event interface specified is supported by the - * implementation this method will return a new Event of - * the interface type requested. If the Event is to be - * dispatched via the dispatchEvent method the - * appropriate event init method must be called after creation in - * order to initialize the Event's values. As an example, - * a user wishing to synthesize some kind of UIEvent - * would call createEvent with the parameter "UIEvents". - * The initUIEvent method could then be called on the - * newly created UIEvent to set the specific type of - * UIEvent to be dispatched and set its context information.The - * createEvent method is used in creating - * Events when it is either inconvenient or unnecessary - * for the user to create an Event themselves. In cases - * where the implementation provided Event is - * insufficient, users may supply their own Event - * implementations for use with the dispatchEvent method. - * @return The newly created Event - * @exception DOMException - * NOT_SUPPORTED_ERR: Raised if the implementation does not support the - * type of Event interface requested - */ - public Event createEvent(String eventType) - throws DOMException; - -} diff --git a/xml/src/main/java/org/w3c/dom/events/Event.java b/xml/src/main/java/org/w3c/dom/events/Event.java deleted file mode 100644 index 14a9239..0000000 --- a/xml/src/main/java/org/w3c/dom/events/Event.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -/** - * The Event interface is used to provide contextual information - * about an event to the handler processing the event. An object which - * implements the Event interface is generally passed as the - * first parameter to an event handler. More specific context information is - * passed to event handlers by deriving additional interfaces from - * Event which contain information directly relating to the - * type of event they accompany. These derived interfaces are also - * implemented by the object passed to the event listener. - *

See also the Document Object Model (DOM) Level 2 Events Specification. - * @since DOM Level 2 - */ -public interface Event { - // PhaseType - /** - * The current event phase is the capturing phase. - */ - public static final short CAPTURING_PHASE = 1; - /** - * The event is currently being evaluated at the target - * EventTarget. - */ - public static final short AT_TARGET = 2; - /** - * The current event phase is the bubbling phase. - */ - public static final short BUBBLING_PHASE = 3; - - /** - * The name of the event (case-insensitive). The name must be an XML name. - */ - public String getType(); - - /** - * Used to indicate the EventTarget to which the event was - * originally dispatched. - */ - public EventTarget getTarget(); - - /** - * Used to indicate the EventTarget whose - * EventListeners are currently being processed. This is - * particularly useful during capturing and bubbling. - */ - public EventTarget getCurrentTarget(); - - /** - * Used to indicate which phase of event flow is currently being - * evaluated. - */ - public short getEventPhase(); - - /** - * Used to indicate whether or not an event is a bubbling event. If the - * event can bubble the value is true, else the value is false. - */ - public boolean getBubbles(); - - /** - * Used to indicate whether or not an event can have its default action - * prevented. If the default action can be prevented the value is true, - * else the value is false. - */ - public boolean getCancelable(); - - /** - * Used to specify the time (in milliseconds relative to the epoch) at - * which the event was created. Due to the fact that some systems may - * not provide this information the value of timeStamp may - * be not available for all events. When not available, a value of 0 - * will be returned. Examples of epoch time are the time of the system - * start or 0:0:0 UTC 1st January 1970. - */ - public long getTimeStamp(); - - /** - * The stopPropagation method is used prevent further - * propagation of an event during event flow. If this method is called - * by any EventListener the event will cease propagating - * through the tree. The event will complete dispatch to all listeners - * on the current EventTarget before event flow stops. This - * method may be used during any stage of event flow. - */ - public void stopPropagation(); - - /** - * If an event is cancelable, the preventDefault method is - * used to signify that the event is to be canceled, meaning any default - * action normally taken by the implementation as a result of the event - * will not occur. If, during any stage of event flow, the - * preventDefault method is called the event is canceled. - * Any default action associated with the event will not occur. Calling - * this method for a non-cancelable event has no effect. Once - * preventDefault has been called it will remain in effect - * throughout the remainder of the event's propagation. This method may - * be used during any stage of event flow. - */ - public void preventDefault(); - - /** - * The initEvent method is used to initialize the value of an - * Event created through the DocumentEvent - * interface. This method may only be called before the - * Event has been dispatched via the - * dispatchEvent method, though it may be called multiple - * times during that phase if necessary. If called multiple times the - * final invocation takes precedence. If called from a subclass of - * Event interface only the values specified in the - * initEvent method are modified, all other attributes are - * left unchanged. - * @param eventTypeArg Specifies the event type. This type may be any - * event type currently defined in this specification or a new event - * type.. The string must be an XML name. Any new event type must not - * begin with any upper, lower, or mixed case version of the string - * "DOM". This prefix is reserved for future DOM event sets. It is - * also strongly recommended that third parties adding their own - * events use their own prefix to avoid confusion and lessen the - * probability of conflicts with other new events. - * @param canBubbleArg Specifies whether or not the event can bubble. - * @param cancelableArg Specifies whether or not the event's default - * action can be prevented. - */ - public void initEvent(String eventTypeArg, - boolean canBubbleArg, - boolean cancelableArg); - -} diff --git a/xml/src/main/java/org/w3c/dom/events/EventException.java b/xml/src/main/java/org/w3c/dom/events/EventException.java deleted file mode 100644 index 7a6ff26..0000000 --- a/xml/src/main/java/org/w3c/dom/events/EventException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -/** - * Event operations may throw an EventException as specified in - * their method descriptions. - *

See also the Document Object Model (DOM) Level 2 Events Specification. - * @since DOM Level 2 - */ -public class EventException extends RuntimeException { - public EventException(short code, String message) { - super(message); - this.code = code; - } - public short code; - // EventExceptionCode - /** - * If the Event's type was not specified by initializing the - * event before the method was called. Specification of the Event's type - * as null or an empty string will also trigger this - * exception. - */ - public static final short UNSPECIFIED_EVENT_TYPE_ERR = 0; - -} diff --git a/xml/src/main/java/org/w3c/dom/events/EventListener.java b/xml/src/main/java/org/w3c/dom/events/EventListener.java deleted file mode 100644 index 1df8020..0000000 --- a/xml/src/main/java/org/w3c/dom/events/EventListener.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -/** - * The EventListener interface is the primary method for - * handling events. Users implement the EventListener interface - * and register their listener on an EventTarget using the - * AddEventListener method. The users should also remove their - * EventListener from its EventTarget after they - * have completed using the listener. - *

When a Node is copied using the cloneNode - * method the EventListeners attached to the source - * Node are not attached to the copied Node. If - * the user wishes the same EventListeners to be added to the - * newly created copy the user must add them manually. - *

See also the Document Object Model (DOM) Level 2 Events Specification. - * @since DOM Level 2 - */ -public interface EventListener { - /** - * This method is called whenever an event occurs of the type for which - * the EventListener interface was registered. - * @param evt The Event contains contextual information - * about the event. It also contains the stopPropagation - * and preventDefault methods which are used in - * determining the event's flow and default action. - */ - public void handleEvent(Event evt); - -} diff --git a/xml/src/main/java/org/w3c/dom/events/EventTarget.java b/xml/src/main/java/org/w3c/dom/events/EventTarget.java deleted file mode 100644 index f076636..0000000 --- a/xml/src/main/java/org/w3c/dom/events/EventTarget.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -/** - * The EventTarget interface is implemented by all - * Nodes in an implementation which supports the DOM Event - * Model. Therefore, this interface can be obtained by using - * binding-specific casting methods on an instance of the Node - * interface. The interface allows registration and removal of - * EventListeners on an EventTarget and dispatch - * of events to that EventTarget. - *

See also the Document Object Model (DOM) Level 2 Events Specification. - * @since DOM Level 2 - */ -public interface EventTarget { - /** - * This method allows the registration of event listeners on the event - * target. If an EventListener is added to an - * EventTarget while it is processing an event, it will not - * be triggered by the current actions but may be triggered during a - * later stage of event flow, such as the bubbling phase. - *
If multiple identical EventListeners are registered - * on the same EventTarget with the same parameters the - * duplicate instances are discarded. They do not cause the - * EventListener to be called twice and since they are - * discarded they do not need to be removed with the - * removeEventListener method. - * @param type The event type for which the user is registering - * @param listener The listener parameter takes an interface - * implemented by the user which contains the methods to be called - * when the event occurs. - * @param useCapture If true, useCapture indicates that the - * user wishes to initiate capture. After initiating capture, all - * events of the specified type will be dispatched to the registered - * EventListener before being dispatched to any - * EventTargets beneath them in the tree. Events which - * are bubbling upward through the tree will not trigger an - * EventListener designated to use capture. - */ - public void addEventListener(String type, - EventListener listener, - boolean useCapture); - - /** - * This method allows the removal of event listeners from the event - * target. If an EventListener is removed from an - * EventTarget while it is processing an event, it will not - * be triggered by the current actions. EventListeners can - * never be invoked after being removed. - *
Calling removeEventListener with arguments which do - * not identify any currently registered EventListener on - * the EventTarget has no effect. - * @param type Specifies the event type of the EventListener - * being removed. - * @param listener The EventListener parameter indicates the - * EventListener to be removed. - * @param useCapture Specifies whether the EventListener - * being removed was registered as a capturing listener or not. If a - * listener was registered twice, one with capture and one without, - * each must be removed separately. Removal of a capturing listener - * does not affect a non-capturing version of the same listener, and - * vice versa. - */ - public void removeEventListener(String type, - EventListener listener, - boolean useCapture); - - /** - * This method allows the dispatch of events into the implementations - * event model. Events dispatched in this manner will have the same - * capturing and bubbling behavior as events dispatched directly by the - * implementation. The target of the event is the - * EventTarget on which dispatchEvent is - * called. - * @param evt Specifies the event type, behavior, and contextual - * information to be used in processing the event. - * @return The return value of dispatchEvent indicates - * whether any of the listeners which handled the event called - * preventDefault. If preventDefault was - * called the value is false, else the value is true. - * @exception EventException - * UNSPECIFIED_EVENT_TYPE_ERR: Raised if the Event's type - * was not specified by initializing the event before - * dispatchEvent was called. Specification of the - * Event's type as null or an empty string - * will also trigger this exception. - */ - public boolean dispatchEvent(Event evt) - throws EventException; - -} diff --git a/xml/src/main/java/org/w3c/dom/events/MouseEvent.java b/xml/src/main/java/org/w3c/dom/events/MouseEvent.java deleted file mode 100644 index be78035..0000000 --- a/xml/src/main/java/org/w3c/dom/events/MouseEvent.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -import org.w3c.dom.views.AbstractView; - -/** - * The MouseEvent interface provides specific contextual - * information associated with Mouse events. - *

The detail attribute inherited from UIEvent - * indicates the number of times a mouse button has been pressed and - * released over the same screen location during a user action. The - * attribute value is 1 when the user begins this action and increments by 1 - * for each full sequence of pressing and releasing. If the user moves the - * mouse between the mousedown and mouseup the value will be set to 0, - * indicating that no click is occurring. - *

In the case of nested elements mouse events are always targeted at the - * most deeply nested element. Ancestors of the targeted element may use - * bubbling to obtain notification of mouse events which occur within its - * descendent elements. - *

See also the Document Object Model (DOM) Level 2 Events Specification. - * @since DOM Level 2 - */ -public interface MouseEvent extends UIEvent { - /** - * The horizontal coordinate at which the event occurred relative to the - * origin of the screen coordinate system. - */ - public int getScreenX(); - - /** - * The vertical coordinate at which the event occurred relative to the - * origin of the screen coordinate system. - */ - public int getScreenY(); - - /** - * The horizontal coordinate at which the event occurred relative to the - * DOM implementation's client area. - */ - public int getClientX(); - - /** - * The vertical coordinate at which the event occurred relative to the DOM - * implementation's client area. - */ - public int getClientY(); - - /** - * Used to indicate whether the 'ctrl' key was depressed during the firing - * of the event. - */ - public boolean getCtrlKey(); - - /** - * Used to indicate whether the 'shift' key was depressed during the - * firing of the event. - */ - public boolean getShiftKey(); - - /** - * Used to indicate whether the 'alt' key was depressed during the firing - * of the event. On some platforms this key may map to an alternative - * key name. - */ - public boolean getAltKey(); - - /** - * Used to indicate whether the 'meta' key was depressed during the firing - * of the event. On some platforms this key may map to an alternative - * key name. - */ - public boolean getMetaKey(); - - /** - * During mouse events caused by the depression or release of a mouse - * button, button is used to indicate which mouse button - * changed state. The values for button range from zero to - * indicate the left button of the mouse, one to indicate the middle - * button if present, and two to indicate the right button. For mice - * configured for left handed use in which the button actions are - * reversed the values are instead read from right to left. - */ - public short getButton(); - - /** - * Used to identify a secondary EventTarget related to a UI - * event. Currently this attribute is used with the mouseover event to - * indicate the EventTarget which the pointing device - * exited and with the mouseout event to indicate the - * EventTarget which the pointing device entered. - */ - public EventTarget getRelatedTarget(); - - /** - * The initMouseEvent method is used to initialize the value - * of a MouseEvent created through the - * DocumentEvent interface. This method may only be called - * before the MouseEvent has been dispatched via the - * dispatchEvent method, though it may be called multiple - * times during that phase if necessary. If called multiple times, the - * final invocation takes precedence. - * @param typeArg Specifies the event type. - * @param canBubbleArg Specifies whether or not the event can bubble. - * @param cancelableArg Specifies whether or not the event's default - * action can be prevented. - * @param viewArg Specifies the Event's - * AbstractView. - * @param detailArg Specifies the Event's mouse click count. - * @param screenXArg Specifies the Event's screen x - * coordinate - * @param screenYArg Specifies the Event's screen y - * coordinate - * @param clientXArg Specifies the Event's client x - * coordinate - * @param clientYArg Specifies the Event's client y - * coordinate - * @param ctrlKeyArg Specifies whether or not control key was depressed - * during the Event. - * @param altKeyArg Specifies whether or not alt key was depressed during - * the Event. - * @param shiftKeyArg Specifies whether or not shift key was depressed - * during the Event. - * @param metaKeyArg Specifies whether or not meta key was depressed - * during the Event. - * @param buttonArg Specifies the Event's mouse button. - * @param relatedTargetArg Specifies the Event's related - * EventTarget. - */ - public void initMouseEvent(String typeArg, - boolean canBubbleArg, - boolean cancelableArg, - AbstractView viewArg, - int detailArg, - int screenXArg, - int screenYArg, - int clientXArg, - int clientYArg, - boolean ctrlKeyArg, - boolean altKeyArg, - boolean shiftKeyArg, - boolean metaKeyArg, - short buttonArg, - EventTarget relatedTargetArg); - -} diff --git a/xml/src/main/java/org/w3c/dom/events/MutationEvent.java b/xml/src/main/java/org/w3c/dom/events/MutationEvent.java deleted file mode 100644 index 3db4003..0000000 --- a/xml/src/main/java/org/w3c/dom/events/MutationEvent.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -import org.w3c.dom.Node; - -/** - * The MutationEvent interface provides specific contextual - * information associated with Mutation events. - *

See also the Document Object Model (DOM) Level 2 Events Specification. - * @since DOM Level 2 - */ -public interface MutationEvent extends Event { - // attrChangeType - /** - * The Attr was modified in place. - */ - public static final short MODIFICATION = 1; - /** - * The Attr was just added. - */ - public static final short ADDITION = 2; - /** - * The Attr was just removed. - */ - public static final short REMOVAL = 3; - - /** - * relatedNode is used to identify a secondary node related - * to a mutation event. For example, if a mutation event is dispatched - * to a node indicating that its parent has changed, the - * relatedNode is the changed parent. If an event is - * instead dispatched to a subtree indicating a node was changed within - * it, the relatedNode is the changed node. In the case of - * the DOMAttrModified event it indicates the Attr node - * which was modified, added, or removed. - */ - public Node getRelatedNode(); - - /** - * prevValue indicates the previous value of the - * Attr node in DOMAttrModified events, and of the - * CharacterData node in DOMCharacterDataModified events. - */ - public String getPrevValue(); - - /** - * newValue indicates the new value of the Attr - * node in DOMAttrModified events, and of the CharacterData - * node in DOMCharacterDataModified events. - */ - public String getNewValue(); - - /** - * attrName indicates the name of the changed - * Attr node in a DOMAttrModified event. - */ - public String getAttrName(); - - /** - * attrChange indicates the type of change which triggered - * the DOMAttrModified event. The values can be MODIFICATION - * , ADDITION, or REMOVAL. - */ - public short getAttrChange(); - - /** - * The initMutationEvent method is used to initialize the - * value of a MutationEvent created through the - * DocumentEvent interface. This method may only be called - * before the MutationEvent has been dispatched via the - * dispatchEvent method, though it may be called multiple - * times during that phase if necessary. If called multiple times, the - * final invocation takes precedence. - * @param typeArg Specifies the event type. - * @param canBubbleArg Specifies whether or not the event can bubble. - * @param cancelableArg Specifies whether or not the event's default - * action can be prevented. - * @param relatedNodeArg Specifies the Event's related Node. - * @param prevValueArg Specifies the Event's - * prevValue attribute. This value may be null. - * @param newValueArg Specifies the Event's - * newValue attribute. This value may be null. - * @param attrNameArg Specifies the Event's - * attrName attribute. This value may be null. - * @param attrChangeArg Specifies the Event's - * attrChange attribute - */ - public void initMutationEvent(String typeArg, - boolean canBubbleArg, - boolean cancelableArg, - Node relatedNodeArg, - String prevValueArg, - String newValueArg, - String attrNameArg, - short attrChangeArg); - -} diff --git a/xml/src/main/java/org/w3c/dom/events/UIEvent.java b/xml/src/main/java/org/w3c/dom/events/UIEvent.java deleted file mode 100644 index 15affe8..0000000 --- a/xml/src/main/java/org/w3c/dom/events/UIEvent.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -import org.w3c.dom.views.AbstractView; - -/** - * The UIEvent interface provides specific contextual information - * associated with User Interface events. - *

See also the Document Object Model (DOM) Level 2 Events Specification. - * @since DOM Level 2 - */ -public interface UIEvent extends Event { - /** - * The view attribute identifies the AbstractView - * from which the event was generated. - */ - public AbstractView getView(); - - /** - * Specifies some detail information about the Event, - * depending on the type of event. - */ - public int getDetail(); - - /** - * The initUIEvent method is used to initialize the value of - * a UIEvent created through the DocumentEvent - * interface. This method may only be called before the - * UIEvent has been dispatched via the - * dispatchEvent method, though it may be called multiple - * times during that phase if necessary. If called multiple times, the - * final invocation takes precedence. - * @param typeArg Specifies the event type. - * @param canBubbleArg Specifies whether or not the event can bubble. - * @param cancelableArg Specifies whether or not the event's default - * action can be prevented. - * @param viewArg Specifies the Event's - * AbstractView. - * @param detailArg Specifies the Event's detail. - */ - public void initUIEvent(String typeArg, - boolean canBubbleArg, - boolean cancelableArg, - AbstractView viewArg, - int detailArg); - -} diff --git a/xml/src/main/java/org/w3c/dom/ls/LSLoadEvent.java b/xml/src/main/java/org/w3c/dom/ls/LSLoadEvent.java deleted file mode 100644 index 601a5be..0000000 --- a/xml/src/main/java/org/w3c/dom/ls/LSLoadEvent.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2004 World Wide Web Consortium, - * - * (Massachusetts Institute of Technology, European Research Consortium for - * Informatics and Mathematics, Keio University). All Rights Reserved. This - * work is distributed under the W3C(r) Software License [1] 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. - * - * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - */ - -package org.w3c.dom.ls; - -import org.w3c.dom.Document; -import org.w3c.dom.events.Event; - -/** - * This interface represents a load event object that signals the completion - * of a document load. - *

See also the Document Object Model (DOM) Level 3 Load -and Save Specification. - */ -public interface LSLoadEvent extends Event { - /** - * The document that finished loading. - */ - public Document getNewDocument(); - - /** - * The input source that was parsed. - */ - public LSInput getInput(); - -} diff --git a/xml/src/main/java/org/w3c/dom/ls/LSProgressEvent.java b/xml/src/main/java/org/w3c/dom/ls/LSProgressEvent.java deleted file mode 100644 index da98e14..0000000 --- a/xml/src/main/java/org/w3c/dom/ls/LSProgressEvent.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2004 World Wide Web Consortium, - * - * (Massachusetts Institute of Technology, European Research Consortium for - * Informatics and Mathematics, Keio University). All Rights Reserved. This - * work is distributed under the W3C(r) Software License [1] 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. - * - * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - */ - -package org.w3c.dom.ls; - -import org.w3c.dom.events.Event; - -/** - * This interface represents a progress event object that notifies the - * application about progress as a document is parsed. It extends the - * Event interface defined in [DOM Level 3 Events] - * . - *

The units used for the attributes position and - * totalSize are not specified and can be implementation and - * input dependent. - *

See also the Document Object Model (DOM) Level 3 Load -and Save Specification. - */ -public interface LSProgressEvent extends Event { - /** - * The input source that is being parsed. - */ - public LSInput getInput(); - - /** - * The current position in the input source, including all external - * entities and other resources that have been read. - */ - public int getPosition(); - - /** - * The total size of the document including all external resources, this - * number might change as a document is being parsed if references to - * more external resources are seen. A value of 0 is - * returned if the total size cannot be determined or estimated. - */ - public int getTotalSize(); - -} diff --git a/xml/src/main/java/org/w3c/dom/ls/LSSerializer.java b/xml/src/main/java/org/w3c/dom/ls/LSSerializer.java index e7b6350..33b094a 100644 --- a/xml/src/main/java/org/w3c/dom/ls/LSSerializer.java +++ b/xml/src/main/java/org/w3c/dom/ls/LSSerializer.java @@ -330,7 +330,9 @@ public interface LSSerializer { *
The filter is invoked after the operations requested by the * DOMConfiguration parameters have been applied. For * example, CDATA sections won't be passed to the filter if " - * cdata-sections" is set to false. + * cdata-sections" is set to false. + * + * @hide */ public LSSerializerFilter getFilter(); /** @@ -341,7 +343,9 @@ public interface LSSerializer { *
The filter is invoked after the operations requested by the * DOMConfiguration parameters have been applied. For * example, CDATA sections won't be passed to the filter if " - * cdata-sections" is set to false. + * cdata-sections" is set to false. + * + * @hide */ public void setFilter(LSSerializerFilter filter); diff --git a/xml/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java b/xml/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java index 049459c..9e76b37 100644 --- a/xml/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java +++ b/xml/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java @@ -41,6 +41,8 @@ import org.w3c.dom.traversal.NodeFilter; * document. *

See also the Document Object Model (DOM) Level 3 Load and Save Specification. + * + * @hide */ public interface LSSerializerFilter extends NodeFilter { /** diff --git a/xml/src/main/java/org/w3c/dom/traversal/DocumentTraversal.java b/xml/src/main/java/org/w3c/dom/traversal/DocumentTraversal.java deleted file mode 100644 index bc45ad9..0000000 --- a/xml/src/main/java/org/w3c/dom/traversal/DocumentTraversal.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.traversal; - -import org.w3c.dom.Node; -import org.w3c.dom.DOMException; - -/** - * DocumentTraversal contains methods that create - * NodeIterators and TreeWalkers to traverse a - * node and its children in document order (depth first, pre-order - * traversal, which is equivalent to the order in which the start tags occur - * in the text representation of the document). In DOMs which support the - * Traversal feature, DocumentTraversal will be implemented by - * the same objects that implement the Document interface. - *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. - * @since DOM Level 2 - */ -public interface DocumentTraversal { - /** - * Create a new NodeIterator over the subtree rooted at the - * specified node. - * @param root The node which will be iterated together with its - * children. The NodeIterator is initially positioned - * just before this node. The whatToShow flags and the - * filter, if any, are not considered when setting this position. The - * root must not be null. - * @param whatToShow This flag specifies which node types may appear in - * the logical view of the tree presented by the - * NodeIterator. See the description of - * NodeFilter for the set of possible SHOW_ - * values.These flags can be combined using OR. - * @param filter The NodeFilter to be used with this - * NodeIterator, or null to indicate no - * filter. - * @param entityReferenceExpansion The value of this flag determines - * whether entity reference nodes are expanded. - * @return The newly created NodeIterator. - * @exception DOMException - * NOT_SUPPORTED_ERR: Raised if the specified root is - * null. - */ - public NodeIterator createNodeIterator(Node root, - int whatToShow, - NodeFilter filter, - boolean entityReferenceExpansion) - throws DOMException; - - /** - * Create a new TreeWalker over the subtree rooted at the - * specified node. - * @param root The node which will serve as the root for the - * TreeWalker. The whatToShow flags and the - * NodeFilter are not considered when setting this value; - * any node type will be accepted as the root. The - * currentNode of the TreeWalker is - * initialized to this node, whether or not it is visible. The - * root functions as a stopping point for traversal - * methods that look upward in the document structure, such as - * parentNode and nextNode. The root must - * not be null. - * @param whatToShow This flag specifies which node types may appear in - * the logical view of the tree presented by the - * TreeWalker. See the description of - * NodeFilter for the set of possible SHOW_ - * values.These flags can be combined using OR. - * @param filter The NodeFilter to be used with this - * TreeWalker, or null to indicate no filter. - * @param entityReferenceExpansion If this flag is false, the contents of - * EntityReference nodes are not presented in the logical - * view. - * @return The newly created TreeWalker. - * @exception DOMException - * NOT_SUPPORTED_ERR: Raised if the specified root is - * null. - */ - public TreeWalker createTreeWalker(Node root, - int whatToShow, - NodeFilter filter, - boolean entityReferenceExpansion) - throws DOMException; - -} diff --git a/xml/src/main/java/org/w3c/dom/traversal/NodeFilter.java b/xml/src/main/java/org/w3c/dom/traversal/NodeFilter.java index b9beac4..4d179e7 100644 --- a/xml/src/main/java/org/w3c/dom/traversal/NodeFilter.java +++ b/xml/src/main/java/org/w3c/dom/traversal/NodeFilter.java @@ -31,6 +31,8 @@ import org.w3c.dom.Node; * encouraging code reuse. *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. * @since DOM Level 2 + * + * @hide */ public interface NodeFilter { // Constants returned by acceptNode diff --git a/xml/src/main/java/org/w3c/dom/traversal/NodeIterator.java b/xml/src/main/java/org/w3c/dom/traversal/NodeIterator.java index d1f0d08..e55cd9f 100644 --- a/xml/src/main/java/org/w3c/dom/traversal/NodeIterator.java +++ b/xml/src/main/java/org/w3c/dom/traversal/NodeIterator.java @@ -27,6 +27,8 @@ import org.w3c.dom.DOMException; * DocumentTraversal.createNodeIterator(). *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. * @since DOM Level 2 + * + * @hide */ public interface NodeIterator { /** diff --git a/xml/src/main/java/org/w3c/dom/traversal/TreeWalker.java b/xml/src/main/java/org/w3c/dom/traversal/TreeWalker.java deleted file mode 100644 index f5fff86..0000000 --- a/xml/src/main/java/org/w3c/dom/traversal/TreeWalker.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.traversal; - -import org.w3c.dom.Node; -import org.w3c.dom.DOMException; - -/** - * TreeWalker objects are used to navigate a document tree or - * subtree using the view of the document defined by their - * whatToShow flags and filter (if any). Any function which - * performs navigation using a TreeWalker will automatically - * support any view defined by a TreeWalker. - *

Omitting nodes from the logical view of a subtree can result in a - * structure that is substantially different from the same subtree in the - * complete, unfiltered document. Nodes that are siblings in the - * TreeWalker view may be children of different, widely - * separated nodes in the original view. For instance, consider a - * NodeFilter that skips all nodes except for Text nodes and - * the root node of a document. In the logical view that results, all text - * nodes will be siblings and appear as direct children of the root node, no - * matter how deeply nested the structure of the original document. - *

See also the Document Object Model (DOM) Level 2 Traversal and Range Specification. - * @since DOM Level 2 - */ -public interface TreeWalker { - /** - * The root node of the TreeWalker, as specified - * when it was created. - */ - public Node getRoot(); - - /** - * This attribute determines which node types are presented via the - * TreeWalker. The available set of constants is defined in - * the NodeFilter interface. Nodes not accepted by - * whatToShow will be skipped, but their children may still - * be considered. Note that this skip takes precedence over the filter, - * if any. - */ - public int getWhatToShow(); - - /** - * The filter used to screen nodes. - */ - public NodeFilter getFilter(); - - /** - * The value of this flag determines whether the children of entity - * reference nodes are visible to the TreeWalker. If false, - * these children and their descendants will be rejected. Note that - * this rejection takes precedence over whatToShow and the - * filter, if any. - *
To produce a view of the document that has entity references - * expanded and does not expose the entity reference node itself, use - * the whatToShow flags to hide the entity reference node - * and set expandEntityReferences to true when creating the - * TreeWalker. To produce a view of the document that has - * entity reference nodes but no entity expansion, use the - * whatToShow flags to show the entity reference node and - * set expandEntityReferences to false. - */ - public boolean getExpandEntityReferences(); - - /** - * The node at which the TreeWalker is currently positioned. - *
Alterations to the DOM tree may cause the current node to no longer - * be accepted by the TreeWalker's associated filter. - * currentNode may also be explicitly set to any node, - * whether or not it is within the subtree specified by the - * root node or would be accepted by the filter and - * whatToShow flags. Further traversal occurs relative to - * currentNode even if it is not part of the current view, - * by applying the filters in the requested direction; if no traversal - * is possible, currentNode is not changed. - */ - public Node getCurrentNode(); - /** - * The node at which the TreeWalker is currently positioned. - *
Alterations to the DOM tree may cause the current node to no longer - * be accepted by the TreeWalker's associated filter. - * currentNode may also be explicitly set to any node, - * whether or not it is within the subtree specified by the - * root node or would be accepted by the filter and - * whatToShow flags. Further traversal occurs relative to - * currentNode even if it is not part of the current view, - * by applying the filters in the requested direction; if no traversal - * is possible, currentNode is not changed. - * @exception DOMException - * NOT_SUPPORTED_ERR: Raised if an attempt is made to set - * currentNode to null. - */ - public void setCurrentNode(Node currentNode) - throws DOMException; - - /** - * Moves to and returns the closest visible ancestor node of the current - * node. If the search for parentNode attempts to step - * upward from the TreeWalker's root node, or - * if it fails to find a visible ancestor node, this method retains the - * current position and returns null. - * @return The new parent node, or null if the current node - * has no parent in the TreeWalker's logical view. - */ - public Node parentNode(); - - /** - * Moves the TreeWalker to the first visible child of the - * current node, and returns the new node. If the current node has no - * visible children, returns null, and retains the current - * node. - * @return The new node, or null if the current node has no - * visible children in the TreeWalker's logical view. - */ - public Node firstChild(); - - /** - * Moves the TreeWalker to the last visible child of the - * current node, and returns the new node. If the current node has no - * visible children, returns null, and retains the current - * node. - * @return The new node, or null if the current node has no - * children in the TreeWalker's logical view. - */ - public Node lastChild(); - - /** - * Moves the TreeWalker to the previous sibling of the - * current node, and returns the new node. If the current node has no - * visible previous sibling, returns null, and retains the - * current node. - * @return The new node, or null if the current node has no - * previous sibling. in the TreeWalker's logical view. - */ - public Node previousSibling(); - - /** - * Moves the TreeWalker to the next sibling of the current - * node, and returns the new node. If the current node has no visible - * next sibling, returns null, and retains the current node. - * @return The new node, or null if the current node has no - * next sibling. in the TreeWalker's logical view. - */ - public Node nextSibling(); - - /** - * Moves the TreeWalker to the previous visible node in - * document order relative to the current node, and returns the new - * node. If the current node has no previous node, or if the search for - * previousNode attempts to step upward from the - * TreeWalker's root node, returns - * null, and retains the current node. - * @return The new node, or null if the current node has no - * previous node in the TreeWalker's logical view. - */ - public Node previousNode(); - - /** - * Moves the TreeWalker to the next visible node in document - * order relative to the current node, and returns the new node. If the - * current node has no next node, or if the search for nextNode attempts - * to step upward from the TreeWalker's root - * node, returns null, and retains the current node. - * @return The new node, or null if the current node has no - * next node in the TreeWalker's logical view. - */ - public Node nextNode(); - -} diff --git a/xml/src/main/java/org/w3c/dom/views/AbstractView.java b/xml/src/main/java/org/w3c/dom/views/AbstractView.java deleted file mode 100644 index 97e8f0e..0000000 --- a/xml/src/main/java/org/w3c/dom/views/AbstractView.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.views; - -/** - * A base interface that all views shall derive from. - *

See also the Document Object Model (DOM) Level 2 Views Specification. - * @since DOM Level 2 - */ -public interface AbstractView { - /** - * The source DocumentView of which this is an - * AbstractView. - */ - public DocumentView getDocument(); - -} diff --git a/xml/src/main/java/org/w3c/dom/views/DocumentView.java b/xml/src/main/java/org/w3c/dom/views/DocumentView.java deleted file mode 100644 index 2cb9eeb..0000000 --- a/xml/src/main/java/org/w3c/dom/views/DocumentView.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.views; - -/** - * The DocumentView interface is implemented by - * Document objects in DOM implementations supporting DOM - * Views. It provides an attribute to retrieve the default view of a - * document. - *

See also the Document Object Model (DOM) Level 2 Views Specification. - * @since DOM Level 2 - */ -public interface DocumentView { - /** - * The default AbstractView for this Document, - * or null if none available. - */ - public AbstractView getDefaultView(); - -} -- cgit v1.1 From 1ec94feeb09591c30996c7c0834d6f131e204922 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Fri, 19 Feb 2010 09:22:21 -0800 Subject: Filling in some gaps in our XML DOM v3 API. Specifically, these methods on Node: - setTextContent() - isSameNode() - lookupPrefix() - lookupNamespaceURI() In order to implement the last 2 I needed to fix our KXml parser to include namespace attributes (ie. xmlns) in the pulled document. Previously these were being elided. Added a new testcase to verify our behaviour. It passes the RI. On Dalvik we have a small issue with entity declarations. Added a new testcase to verify Node.getBaseURI(). This test fails because the method isn't implemented. Part of this test required moving a method out to Support_Resources.java; in order to verify the BaseURI the XML must be read from a file and not a stream (so that path information exists). Also... - Style cleanup: changing static calls to look like static calls. - Efficiency: avoiding concatenating with "" when unnecessary - Duplication: sharing prefix validation between attributes and elements - Renaming NodeTests to NodeTest for vogar-friendliness Outstanding: - I need to write a test for setTextContent(). --- .../java/org/apache/harmony/xml/dom/AttrImpl.java | 27 +- .../org/apache/harmony/xml/dom/ElementImpl.java | 28 +-- .../java/org/apache/harmony/xml/dom/NodeImpl.java | 251 ++++++++++++++++-- .../harmony/xml/parsers/DocumentBuilderImpl.java | 4 +- xml/src/main/java/org/kxml2/io/KXmlParser.java | 47 +++- xml/src/main/java/org/w3c/dom/Attr.java | 2 +- .../api/javax/xml/parsers/DocumentBuilderTest.java | 25 +- xml/src/test/java/tests/xml/AllTests.java | 2 +- xml/src/test/java/tests/xml/DomTest.java | 280 +++++++++++++++++++++ xml/src/test/java/tests/xml/NodeTest.java | 86 +++++++ xml/src/test/java/tests/xml/NodeTests.java | 47 ---- 11 files changed, 662 insertions(+), 137 deletions(-) create mode 100644 xml/src/test/java/tests/xml/DomTest.java create mode 100644 xml/src/test/java/tests/xml/NodeTest.java delete mode 100644 xml/src/test/java/tests/xml/NodeTests.java (limited to 'xml/src') diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java index 59a8b78..c071899 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java @@ -73,7 +73,7 @@ public class AttrImpl extends NodeImpl implements Attr { throw new DOMException(DOMException.NAMESPACE_ERR, localName); } - if (!document.isXMLIdentifier(localName)) { + if (!DocumentImpl.isXMLIdentifier(localName)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, localName); } @@ -90,11 +90,11 @@ public class AttrImpl extends NodeImpl implements Attr { String prefix = name.substring(0, prefixSeparator); String localName = name.substring(prefixSeparator + 1); - if (!document.isXMLIdentifier(prefix) || !document.isXMLIdentifier(localName)) { + if (!DocumentImpl.isXMLIdentifier(prefix) || !DocumentImpl.isXMLIdentifier(localName)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); } } else { - if (!document.isXMLIdentifier(name)) { + if (!DocumentImpl.isXMLIdentifier(name)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); } } @@ -108,7 +108,9 @@ public class AttrImpl extends NodeImpl implements Attr { } public String getName() { - return (prefix != null ? prefix + ":" : "") + localName; + return prefix != null + ? prefix + ":" + localName + : localName; } @Override @@ -154,22 +156,7 @@ public class AttrImpl extends NodeImpl implements Attr { @Override public void setPrefix(String prefix) { - if (!namespaceAware) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - - if (prefix != null) { - if (namespaceURI == null - || !DocumentImpl.isXMLIdentifier(prefix) - || ("xmlns".equals(prefix) - && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) - || ("xml".equals(prefix) - && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI))) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - } - - this.prefix = prefix; + this.prefix = validatePrefix(prefix, namespaceAware, namespaceURI); } public void setValue(String value) throws DOMException { diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java index 230e444..df1383d 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java @@ -65,7 +65,7 @@ public class ElementImpl extends InnerNodeImpl implements Element { qualifiedName = qualifiedName.substring(p + 1); } - if (!document.isXMLIdentifier(qualifiedName)) { + if (!DocumentImpl.isXMLIdentifier(qualifiedName)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, qualifiedName); } @@ -82,11 +82,11 @@ public class ElementImpl extends InnerNodeImpl implements Element { String prefix = name.substring(0, p); String localName = name.substring(p + 1); - if (!document.isXMLIdentifier(prefix) || !document.isXMLIdentifier(localName)) { + if (!DocumentImpl.isXMLIdentifier(prefix) || !DocumentImpl.isXMLIdentifier(localName)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); } } else { - if (!document.isXMLIdentifier(name)) { + if (!DocumentImpl.isXMLIdentifier(name)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); } } @@ -241,7 +241,9 @@ public class ElementImpl extends InnerNodeImpl implements Element { } public String getTagName() { - return (prefix != null ? prefix + ":" : "") + localName; + return prefix != null + ? prefix + ":" + localName + : localName; } public boolean hasAttribute(String name) { @@ -281,7 +283,7 @@ public class ElementImpl extends InnerNodeImpl implements Element { throw new DOMException(DOMException.NOT_FOUND_ERR, null); } - attributes.remove(oldAttr); + attributes.remove(oldAttrImpl); oldAttrImpl.ownerElement = null; return oldAttrImpl; @@ -362,21 +364,7 @@ public class ElementImpl extends InnerNodeImpl implements Element { @Override public void setPrefix(String prefix) { - if (!namespaceAware) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - - if (prefix != null) { - if (namespaceURI == null || !document.isXMLIdentifier(prefix)) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - - if ("xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI)) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - } - - this.prefix = prefix; + this.prefix = validatePrefix(prefix, namespaceAware, namespaceURI); } public class ElementAttrNamedNodeMapImpl implements NamedNodeMap { diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java index b752506..57ff7dc 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java @@ -16,6 +16,7 @@ package org.apache.harmony.xml.dom; +import org.w3c.dom.Attr; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; @@ -24,16 +25,15 @@ import org.w3c.dom.NodeList; import org.w3c.dom.UserDataHandler; /** - * Provides a straightforward implementation of the corresponding W3C DOM - * interface. The class is used internally only, thus only notable members that - * are not in the original interface are documented (the W3C docs are quite - * extensive). Hope that's ok. - *

- * Some of the fields may have package visibility, so other classes belonging to - * the DOM implementation can easily access them while maintaining the DOM tree - * structure. - *

- * This class represents a Node that has neither a parent nor children. + * A straightforward implementation of the corresponding W3C DOM node. + * + *

Some fields have package visibility so other classes can access them while + * maintaining the DOM structure. + * + *

This class represents a Node that has neither a parent nor children. + * Subclasses may have either. + * + *

Some code was adapted from Apache Xerces. */ public abstract class NodeImpl implements Node { @@ -142,6 +142,29 @@ public abstract class NodeImpl implements Node { } /** + * Validates the element or attribute namespace prefix on this node. + * + * @param namespaceAware whether this node is namespace aware + * @param namespaceURI this node's namespace URI + */ + protected String validatePrefix(String prefix, boolean namespaceAware, String namespaceURI) { + if (!namespaceAware) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + + if (prefix != null) { + if (namespaceURI == null + || !DocumentImpl.isXMLIdentifier(prefix) + || "xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI) + || "xmlns".equals(prefix) && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + } + + return prefix; + } + + /** * Checks whether a required string matches an actual string. This utility * method is used for comparing namespaces and such. It takes into account * null arguments and the "*" special case. @@ -190,7 +213,34 @@ public abstract class NodeImpl implements Node { } public String getBaseURI() { - return null; // TODO + /* + * TODO: implement. For reference, here's Xerces' behaviour: + * + * In all cases, the returned URI should be sanitized before it is + * returned. If the URI is malformed, null should be returned instead. + * + * For document nodes, this should return a member field that's + * initialized by the parser. + * + * For element nodes, this should first look for the xml:base attribute. + * if that exists and is absolute, it should be returned. + * if that exists and is relative, it should be resolved to the parent's base URI + * if it doesn't exist, the parent's baseURI should be returned + * + * For entity nodes, if a base URI exists that should be returned. + * Otherwise the document's base URI should be returned + * + * For entity references, if a base URI exists that should be returned + * otherwise it dereferences the entity (via the document) and uses the + * entity's base URI. + * + * For notations, it returns the base URI field. + * + * For processing instructions, it returns the parent's base URI. + * + * For all other node types, it returns null. + */ + return null; } public short compareDocumentPosition(Node other) @@ -210,23 +260,190 @@ public abstract class NodeImpl implements Node { } public void setTextContent(String textContent) throws DOMException { - throw new UnsupportedOperationException(); // TODO + switch (getNodeType()) { + case DOCUMENT_TYPE_NODE: + case DOCUMENT_NODE: + return; // do nothing! + + case ELEMENT_NODE: + case ENTITY_NODE: + case ENTITY_REFERENCE_NODE: + case DOCUMENT_FRAGMENT_NODE: + // remove all existing children + Node child; + while ((child = getFirstChild()) != null) { + removeChild(child); + } + // create a text node to hold the given content + if (textContent != null && textContent.length() != 0){ + appendChild(getOwnerDocument().createTextNode(textContent)); + } + return; + + case ATTRIBUTE_NODE: + case TEXT_NODE: + case CDATA_SECTION_NODE: + case PROCESSING_INSTRUCTION_NODE: + case COMMENT_NODE: + case NOTATION_NODE: + setNodeValue(textContent); + return; + + default: + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, + "Unsupported node type " + getNodeType()); + } } public boolean isSameNode(Node other) { - throw new UnsupportedOperationException(); // TODO + return this == other; } - public String lookupPrefix(String namespaceURI) { - throw new UnsupportedOperationException(); // TODO + /** + * Returns the element whose namespace definitions apply to this node. Use + * this element when mapping prefixes to URIs and vice versa. + */ + private NodeImpl getNamespacingElement() { + switch (this.getNodeType()) { + case ELEMENT_NODE: + return this; + + case DOCUMENT_NODE: + return (NodeImpl) ((Document) this).getDocumentElement(); + + case ENTITY_NODE: + case NOTATION_NODE: + case DOCUMENT_FRAGMENT_NODE: + case DOCUMENT_TYPE_NODE: + return null; + + case ATTRIBUTE_NODE: + return (NodeImpl) ((Attr) this).getOwnerElement(); + + case TEXT_NODE: + case CDATA_SECTION_NODE: + case ENTITY_REFERENCE_NODE: + case PROCESSING_INSTRUCTION_NODE: + case COMMENT_NODE: + return getContainingElement(); + + default: + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, + "Unsupported node type " + getNodeType()); + } + } + + /** + * Returns the nearest ancestor element that contains this node. + */ + private NodeImpl getContainingElement() { + for (Node p = getParentNode(); p != null; p = p.getParentNode()) { + if (p.getNodeType() == ELEMENT_NODE) { + return (NodeImpl) p; + } + } + return null; + } + + public final String lookupPrefix(String namespaceURI) { + if (namespaceURI == null) { + return null; + } + + // the XML specs define some prefixes (like "xml" and "xmlns") but this + // API is explicitly defined to ignore those. + + NodeImpl target = getNamespacingElement(); + for (NodeImpl node = target; node != null; node = node.getContainingElement()) { + // check this element's namespace first + if (namespaceURI.equals(node.getNamespaceURI()) + && target.isPrefixMappedToUri(node.getPrefix(), namespaceURI)) { + return node.getPrefix(); + } + + // search this element for an attribute of this form: + // xmlns:foo="http://namespaceURI" + if (!node.hasAttributes()) { + continue; + } + NamedNodeMap attributes = node.getAttributes(); + for (int i = 0, length = attributes.getLength(); i < length; i++) { + Node attr = attributes.item(i); + if (!"http://www.w3.org/2000/xmlns/".equals(attr.getNamespaceURI()) + || !"xmlns".equals(attr.getPrefix()) + || !namespaceURI.equals(attr.getNodeValue())) { + continue; + } + if (target.isPrefixMappedToUri(attr.getLocalName(), namespaceURI)) { + return attr.getLocalName(); + } + } + } + + return null; + } + + /** + * Returns true if the given prefix is mapped to the given URI on this + * element. Since child elements can redefine prefixes, this check is + * necessary: {@code + * + * + * + * + * } + * + * @param prefix the prefix to find. Nullable. + * @param uri the URI to match. Non-null. + */ + boolean isPrefixMappedToUri(String prefix, String uri) { + if (prefix == null) { + return false; + } + + String actual = lookupNamespaceURI(prefix); + return uri.equals(actual); } public boolean isDefaultNamespace(String namespaceURI) { throw new UnsupportedOperationException(); // TODO } - public String lookupNamespaceURI(String prefix) { - throw new UnsupportedOperationException(); // TODO + public final String lookupNamespaceURI(String prefix) { + NodeImpl target = getNamespacingElement(); + for (NodeImpl node = target; node != null; node = node.getContainingElement()) { + // check this element's namespace first + String nodePrefix = node.getPrefix(); + if (node.getNamespaceURI() != null) { + if (prefix == null // null => default prefix + ? nodePrefix == null + : prefix.equals(nodePrefix)) { + return node.getNamespaceURI(); + } + } + + // search this element for an attribute of the appropriate form. + // default namespace: xmlns="http://resultUri" + // non default: xmlns:specifiedPrefix="http://resultUri" + if (!node.hasAttributes()) { + continue; + } + NamedNodeMap attributes = node.getAttributes(); + for (int i = 0, length = attributes.getLength(); i < length; i++) { + Node attr = attributes.item(i); + if (!"http://www.w3.org/2000/xmlns/".equals(attr.getNamespaceURI())) { + continue; + } + if (prefix == null // null => default prefix + ? "xmlns".equals(attr.getNodeName()) + : "xmlns".equals(attr.getPrefix()) && prefix.equals(attr.getLocalName())) { + String value = attr.getNodeValue(); + return value.length() > 0 ? value : null; + } + } + } + + return null; } public boolean isEqualNode(Node arg) { diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java index 5a3c48c..52240aa 100644 --- a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java @@ -115,8 +115,8 @@ class DocumentBuilderImpl extends DocumentBuilder { Document document = newDocument(); try { - XmlPullParser parser = new KXmlParser(); - + KXmlParser parser = new KXmlParser(); + parser.keepNamespaceAttributes(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, namespaceAware); diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java index c4d8f3d..99eb03b 100644 --- a/xml/src/main/java/org/kxml2/io/KXmlParser.java +++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java @@ -45,6 +45,7 @@ public class KXmlParser implements XmlPullParser { private boolean processNsp; private boolean relaxed; + private boolean keepNamespaceAttributes; // android-added private Hashtable entityMap; private int depth; private String[] elementStack = new String[16]; @@ -80,6 +81,14 @@ public class KXmlParser implements XmlPullParser { private boolean degenerated; private int attributeCount; + + /** + * The current element's attributes arranged in groups of 4: + * i + 0 = attribute namespace URI + * i + 1 = attribute namespace prefix + * i + 2 = attribute qualified name (may contain ":", as in "html:h1") + * i + 3 = attribute value + */ private String[] attributes = new String[16]; // private int stackMismatch = 0; private String error; @@ -100,6 +109,19 @@ public class KXmlParser implements XmlPullParser { new char[Runtime.getRuntime().freeMemory() >= 1048576 ? 8192 : 128]; } + // BEGIN android-added + /** + * Retains namespace attributes like {@code xmlns="http://foo"} or {@code + * xmlns:foo="http:foo"} in pulled elements. Most applications will only be + * interested in the effective namespaces of their elements, so these + * attributes aren't useful. But for structure preserving wrappers like DOM, + * it is necessary to keep the namespace data around. + */ + public void keepNamespaceAttributes() { + this.keepNamespaceAttributes = true; + } + // END android-added + private final boolean isProp(String n1, boolean prop, String n2) { if (!n1.startsWith("http://xmlpull.org/v1/doc/")) return false; @@ -148,14 +170,23 @@ public class KXmlParser implements XmlPullParser { //System.out.println (prefixMap); - System.arraycopy( - attributes, - i + 4, - attributes, - i, - ((--attributeCount) << 2) - i); - - i -= 4; + // BEGIN android-changed + if (keepNamespaceAttributes) { + // explicitly set the namespace for unprefixed attributes + // such as xmlns="http://foo" + attributes[i] = "http://www.w3.org/2000/xmlns/"; + any = true; + } else { + System.arraycopy( + attributes, + i + 4, + attributes, + i, + ((--attributeCount) << 2) - i); + + i -= 4; + } + // END android-changed } } diff --git a/xml/src/main/java/org/w3c/dom/Attr.java b/xml/src/main/java/org/w3c/dom/Attr.java index d9ed6ff..bd7267b 100644 --- a/xml/src/main/java/org/w3c/dom/Attr.java +++ b/xml/src/main/java/org/w3c/dom/Attr.java @@ -176,7 +176,7 @@ public interface Attr extends Node { /** * On retrieval, the value of the attribute is returned as a string. * Character and general entity references are replaced with their - * values. See also the method getAttribute on the + * values. See also the method getAttribute on the * Element interface. *
On setting, this creates a Text node with the unparsed * contents of the string, i.e. any characters that an XML processor diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java index 02b6d80..6b10a0d 100644 --- a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java +++ b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java @@ -34,6 +34,7 @@ import org.xml.sax.SAXParseException; import tests.api.org.xml.sax.support.MethodLogger; import tests.api.org.xml.sax.support.MockHandler; import tests.api.org.xml.sax.support.MockResolver; +import tests.support.resource.Support_Resources; import tests.util.TestEnvironment; import javax.xml.parsers.DocumentBuilder; @@ -41,8 +42,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -272,7 +271,7 @@ public class DocumentBuilderTest extends TestCase { args = {java.io.File.class} ) public void testGetBaseURI() throws IOException, SAXException { - File f = resourceToTmpFile("/simple.xml"); + File f = Support_Resources.resourceToTempFile("/simple.xml"); Document d = db.parse(f); assertTrue(d.getDocumentElement().getBaseURI().startsWith("file://")); } @@ -291,7 +290,7 @@ public class DocumentBuilderTest extends TestCase { args = {java.io.File.class} ) public void test_parseLjava_io_File() throws IOException { - File f = resourceToTmpFile("/simple.xml"); + File f = Support_Resources.resourceToTempFile("/simple.xml"); // case 1: Trivial use. try { @@ -333,7 +332,7 @@ public class DocumentBuilderTest extends TestCase { } // case 4: Try to parse incorrect xml file - f = resourceToTmpFile("/wrong.xml"); + f = Support_Resources.resourceToTempFile("/wrong.xml"); try { db.parse(f); fail("Expected SAXException was not thrown"); @@ -344,22 +343,6 @@ public class DocumentBuilderTest extends TestCase { } } - private File resourceToTmpFile(String path) throws IOException, - FileNotFoundException { - File f = File.createTempFile("out", ".xml"); - f.deleteOnExit(); - FileOutputStream out = new FileOutputStream(f); - - InputStream xml = getClass().getResourceAsStream(path); - while (xml.available() > 0) { - out.write(xml.read()); - } - out.flush(); - out.close(); - xml.close(); - return f; - } - /** * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream) * Case 1: Try to parse correct xml document. diff --git a/xml/src/test/java/tests/xml/AllTests.java b/xml/src/test/java/tests/xml/AllTests.java index 45ca18e..89da364 100644 --- a/xml/src/test/java/tests/xml/AllTests.java +++ b/xml/src/test/java/tests/xml/AllTests.java @@ -26,7 +26,7 @@ public class AllTests { suite.addTestSuite(SimpleParserTest.class); suite.addTestSuite(SimpleBuilderTest.class); - suite.addTestSuite(NodeTests.class); + suite.addTestSuite(NodeTest.class); //suite.addTest(tests.org.w3c.dom.AllTests.suite()); suite.addTest(tests.api.javax.xml.parsers.AllTests.suite()); diff --git a/xml/src/test/java/tests/xml/DomTest.java b/xml/src/test/java/tests/xml/DomTest.java new file mode 100644 index 0000000..d6031ed --- /dev/null +++ b/xml/src/test/java/tests/xml/DomTest.java @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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 tests.xml; + +import junit.framework.TestCase; +import org.w3c.dom.Attr; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.Entity; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; +import org.xml.sax.InputSource; + +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Construct a DOM and then interrogate it. + */ +public class DomTest extends TestCase { + + private final String xml + = "" + + "]>" + + "

\n" + + " \n" + + " Waffles\n" + + " Belgianof fat)\n" + + " Whipped Cream\n" + + " &sp;\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 60%\n" + + " \n" + + " \n" + + " \n" + + ""; + + private Document document; + private DocumentType doctype; + private Entity sp; + private Element menu; + private Element item; + private Attr itemXmlns; + private Attr itemXmlnsA; + private Element name; + private Attr standard; + private Attr deluxe; + private Element description; + private Text descriptionText1; + private CDATASection descriptionText2; + private Text descriptionText3; + private Element option1; + private Element option2; + private Node option2Reference; // Text on RI, EntityReference on Dalvik + private ProcessingInstruction wafflemaker; + private Element nutrition; + private Element vitamins; + private Attr vitaminsXmlnsA; + private Comment comment; + private Element vitaminc; + private Text vitamincText; + + private List allNodes; + + @Override protected void setUp() throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + + document = factory.newDocumentBuilder() + .parse(new InputSource(new StringReader(xml))); + + // doctype nodes + doctype = document.getDoctype(); + if (doctype.getEntities() != null) { + sp = (Entity) doctype.getEntities().item(0); + } + + // document nodes + menu = document.getDocumentElement(); + item = (Element) menu.getChildNodes().item(1); + itemXmlns = item.getAttributeNode("xmlns"); + itemXmlnsA = item.getAttributeNode("xmlns:a"); + name = (Element) item.getChildNodes().item(1); + standard = name.getAttributeNode("a:standard"); + deluxe = name.getAttributeNode("deluxe"); + description = (Element) item.getChildNodes().item(3); + descriptionText1 = (Text) description.getChildNodes().item(0); + descriptionText2 = (CDATASection) description.getChildNodes().item(1); + descriptionText3 = (Text) description.getChildNodes().item(2); + option1 = (Element) item.getChildNodes().item(5); + option2 = (Element) item.getChildNodes().item(7); + option2Reference = option2.getChildNodes().item(0); + wafflemaker = (ProcessingInstruction) item.getChildNodes().item(9); + nutrition = (Element) item.getChildNodes().item(11); + vitamins = (Element) nutrition.getChildNodes().item(1); + vitaminsXmlnsA = vitamins.getAttributeNode("xmlns:a"); + comment = (Comment) vitamins.getChildNodes().item(1); + vitaminc = (Element) vitamins.getChildNodes().item(3); + vitamincText = (Text) vitaminc.getChildNodes().item(0); + + allNodes = new ArrayList(); + + if (sp != null) { + allNodes.add(sp); + } + + allNodes.addAll(Arrays.asList(document, doctype, menu, item, itemXmlns, + itemXmlnsA, name, standard, deluxe, description, + descriptionText1, descriptionText2, descriptionText3, option1, + option2, option2Reference, wafflemaker, nutrition, vitamins, + vitaminsXmlnsA, comment, vitaminc, vitamincText)); + } + + /** + * Android's parsed DOM doesn't include entity declarations. These nodes will + * only be tested for implementations that support them. + */ + public void testEntityDeclarations() { + assertNotNull("This implementation does not parse entity declarations", sp); + } + + public void testLookupNamespaceURIByPrefix() { + assertEquals(null, doctype.lookupNamespaceURI("a")); + if (sp != null) { + assertEquals(null, sp.lookupNamespaceURI("a")); + } + assertEquals(null, document.lookupNamespaceURI("a")); + assertEquals(null, menu.lookupNamespaceURI("a")); + assertEquals("http://addons", item.lookupNamespaceURI("a")); + assertEquals("http://addons", itemXmlns.lookupNamespaceURI("a")); + assertEquals("http://addons", itemXmlnsA.lookupNamespaceURI("a")); + assertEquals("http://addons", name.lookupNamespaceURI("a")); + assertEquals("http://addons", standard.lookupNamespaceURI("a")); + assertEquals("http://addons", deluxe.lookupNamespaceURI("a")); + assertEquals("http://addons", description.lookupNamespaceURI("a")); + assertEquals("http://addons", descriptionText1.lookupNamespaceURI("a")); + assertEquals("http://addons", descriptionText2.lookupNamespaceURI("a")); + assertEquals("http://addons", descriptionText3.lookupNamespaceURI("a")); + assertEquals("http://addons", option1.lookupNamespaceURI("a")); + assertEquals("http://addons", option2.lookupNamespaceURI("a")); + assertEquals("http://addons", option2Reference.lookupNamespaceURI("a")); + assertEquals("http://addons", wafflemaker.lookupNamespaceURI("a")); + assertEquals("http://addons", nutrition.lookupNamespaceURI("a")); + assertEquals("http://usda", vitamins.lookupNamespaceURI("a")); + assertEquals("http://usda", vitaminsXmlnsA.lookupNamespaceURI("a")); + assertEquals("http://usda", comment.lookupNamespaceURI("a")); + assertEquals("http://usda", vitaminc.lookupNamespaceURI("a")); + assertEquals("http://usda", vitamincText.lookupNamespaceURI("a")); + } + + public void testLookupNamespaceURIWithNullPrefix() { + assertEquals(null, document.lookupNamespaceURI(null)); + assertEquals(null, doctype.lookupNamespaceURI(null)); + if (sp != null) { + assertEquals(null, sp.lookupNamespaceURI(null)); + } + assertEquals(null, menu.lookupNamespaceURI(null)); + assertEquals("http://food", item.lookupNamespaceURI(null)); + assertEquals("http://food", itemXmlns.lookupNamespaceURI(null)); + assertEquals("http://food", itemXmlnsA.lookupNamespaceURI(null)); + assertEquals("http://food", name.lookupNamespaceURI(null)); + assertEquals("http://food", standard.lookupNamespaceURI(null)); + assertEquals("http://food", deluxe.lookupNamespaceURI(null)); + assertEquals("http://marketing", description.lookupNamespaceURI(null)); + assertEquals("http://marketing", descriptionText1.lookupNamespaceURI(null)); + assertEquals("http://marketing", descriptionText2.lookupNamespaceURI(null)); + assertEquals("http://marketing", descriptionText3.lookupNamespaceURI(null)); + assertEquals("http://food", option1.lookupNamespaceURI(null)); + assertEquals("http://food", option2.lookupNamespaceURI(null)); + assertEquals("http://food", option2Reference.lookupNamespaceURI(null)); + assertEquals("http://food", wafflemaker.lookupNamespaceURI(null)); + assertEquals("http://food", nutrition.lookupNamespaceURI(null)); + assertEquals("http://food", vitamins.lookupNamespaceURI(null)); + assertEquals("http://food", vitaminsXmlnsA.lookupNamespaceURI(null)); + assertEquals("http://food", comment.lookupNamespaceURI(null)); + assertEquals("http://food", vitaminc.lookupNamespaceURI(null)); + assertEquals("http://food", vitamincText.lookupNamespaceURI(null)); + } + + public void testLookupNamespaceURIWithXmlnsPrefix() { + for (Node node : allNodes) { + assertEquals(null, node.lookupNamespaceURI("xmlns")); + } + } + + public void testLookupPrefixWithShadowedUri() { + assertEquals(null, document.lookupPrefix("http://addons")); + assertEquals(null, doctype.lookupPrefix("http://addons")); + if (sp != null) { + assertEquals(null, sp.lookupPrefix("http://addons")); + } + assertEquals(null, menu.lookupPrefix("http://addons")); + assertEquals("a", item.lookupPrefix("http://addons")); + assertEquals("a", itemXmlns.lookupPrefix("http://addons")); + assertEquals("a", itemXmlnsA.lookupPrefix("http://addons")); + assertEquals("a", name.lookupPrefix("http://addons")); + assertEquals("a", standard.lookupPrefix("http://addons")); + assertEquals("a", deluxe.lookupPrefix("http://addons")); + assertEquals("a", description.lookupPrefix("http://addons")); + assertEquals("a", descriptionText1.lookupPrefix("http://addons")); + assertEquals("a", descriptionText2.lookupPrefix("http://addons")); + assertEquals("a", descriptionText3.lookupPrefix("http://addons")); + assertEquals("a", option1.lookupPrefix("http://addons")); + assertEquals("a", option2.lookupPrefix("http://addons")); + assertEquals("a", option2Reference.lookupPrefix("http://addons")); + assertEquals("a", wafflemaker.lookupPrefix("http://addons")); + assertEquals("a", nutrition.lookupPrefix("http://addons")); + assertEquals(null, vitamins.lookupPrefix("http://addons")); + assertEquals(null, vitaminsXmlnsA.lookupPrefix("http://addons")); + assertEquals(null, comment.lookupPrefix("http://addons")); + assertEquals(null, vitaminc.lookupPrefix("http://addons")); + assertEquals(null, vitamincText.lookupPrefix("http://addons")); + } + + public void testLookupPrefixWithUnusedUri() { + for (Node node : allNodes) { + assertEquals(null, node.lookupPrefix("http://unused")); + } + } + + public void testLookupPrefixWithNullUri() { + for (Node node : allNodes) { + assertEquals(null, node.lookupPrefix(null)); + } + } + + public void testLookupPrefixWithShadowingUri() { + assertEquals(null, document.lookupPrefix("http://usda")); + assertEquals(null, doctype.lookupPrefix("http://usda")); + if (sp != null) { + assertEquals(null, sp.lookupPrefix("http://usda")); + } + assertEquals(null, menu.lookupPrefix("http://usda")); + assertEquals(null, item.lookupPrefix("http://usda")); + assertEquals(null, itemXmlns.lookupPrefix("http://usda")); + assertEquals(null, itemXmlnsA.lookupPrefix("http://usda")); + assertEquals(null, name.lookupPrefix("http://usda")); + assertEquals(null, standard.lookupPrefix("http://usda")); + assertEquals(null, deluxe.lookupPrefix("http://usda")); + assertEquals(null, description.lookupPrefix("http://usda")); + assertEquals(null, descriptionText1.lookupPrefix("http://usda")); + assertEquals(null, descriptionText2.lookupPrefix("http://usda")); + assertEquals(null, descriptionText3.lookupPrefix("http://usda")); + assertEquals(null, option1.lookupPrefix("http://usda")); + assertEquals(null, option2.lookupPrefix("http://usda")); + assertEquals(null, option2Reference.lookupPrefix("http://usda")); + assertEquals(null, wafflemaker.lookupPrefix("http://usda")); + assertEquals(null, nutrition.lookupPrefix("http://usda")); + assertEquals("a", vitamins.lookupPrefix("http://usda")); + assertEquals("a", vitaminsXmlnsA.lookupPrefix("http://usda")); + assertEquals("a", comment.lookupPrefix("http://usda")); + assertEquals("a", vitaminc.lookupPrefix("http://usda")); + assertEquals("a", vitamincText.lookupPrefix("http://usda")); + } +} diff --git a/xml/src/test/java/tests/xml/NodeTest.java b/xml/src/test/java/tests/xml/NodeTest.java new file mode 100644 index 0000000..dc3a333 --- /dev/null +++ b/xml/src/test/java/tests/xml/NodeTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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 tests.xml; + +import dalvik.annotation.TestTargetClass; +import junit.framework.TestCase; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import tests.support.resource.Support_Resources; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +@TestTargetClass(Node.class) +public class NodeTest extends TestCase { + + /** + * For bug 779: Node#getNextSibling throws IndexOutOfBoundsException. + */ + public void test_getNextSibling() throws Exception { + // Calling getNextSibling when there is no next sibling should return null. + // From http://code.google.com/p/android/issues/detail?id=779. + ByteArrayInputStream bis = new ByteArrayInputStream("".getBytes()); + Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bis); + Node root = document.getDocumentElement(); + assertNull(root.getNextSibling()); + } + + public void testGetBaseUri() throws Exception { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + File file = Support_Resources.resourceToTempFile("/simple.xml"); + Document document = builder.parse(file); + + String baseUri = "file:" + file.getPath(); + assertEquals(baseUri, document.getBaseURI()); + + Element documentElement = document.getDocumentElement(); + for (Node node : flattenSubtree(documentElement)) { + if (node.getNodeType() == Node.ELEMENT_NODE + || node.getNodeType() == Node.DOCUMENT_NODE) { + assertEquals("Unexpected base URI for " + node, baseUri, node.getBaseURI()); + } else { + assertNull("Unexpected base URI for " + node, node.getBaseURI()); + } + } + + // TODO: test other node types + // TODO: test resolution of relative paths + // TODO: test URI santization + } + + private List flattenSubtree(Node subtree) { + List result = new ArrayList(); + traverse(subtree, result); + return result; + } + + private void traverse(Node node, List sink) { + sink.add(node); + + NodeList children = node.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + traverse(children.item(i), sink); + } + } +} diff --git a/xml/src/test/java/tests/xml/NodeTests.java b/xml/src/test/java/tests/xml/NodeTests.java deleted file mode 100644 index e46e216..0000000 --- a/xml/src/test/java/tests/xml/NodeTests.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * 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 tests.xml; - -import dalvik.annotation.TestLevel; -import dalvik.annotation.TestTargetNew; -import dalvik.annotation.TestTargetClass; - -import junit.framework.TestCase; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import java.io.ByteArrayInputStream; -import javax.xml.parsers.DocumentBuilderFactory; - -@TestTargetClass(Node.class) -public class NodeTests extends TestCase { - @TestTargetNew( - level = TestLevel.PARTIAL, - notes = "Issue #779: org.w3c.dom.Node#getNextSibling throws IndexOutOfBoundsException.", - method = "getNextSibling", - args = {} - ) - public void test_getNextSibling() throws Exception { - // Calling getNextSibling when there is no next sibling should return null. - // From http://code.google.com/p/android/issues/detail?id=779. - ByteArrayInputStream bis = new ByteArrayInputStream("".getBytes()); - Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bis); - Node root = document.getDocumentElement(); - assertNull(root.getNextSibling()); - } -} -- cgit v1.1 From ea5adee4813216359fda6529e7064c42ccdbc4cd Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Fri, 19 Feb 2010 11:18:41 -0800 Subject: DOM setTextContent() tests and implementation fixes. --- .../java/org/apache/harmony/xml/dom/AttrImpl.java | 5 - .../java/org/apache/harmony/xml/dom/NodeImpl.java | 34 ++++- .../java/org/apache/harmony/xml/dom/TextImpl.java | 5 - xml/src/test/java/tests/xml/DomTest.java | 156 ++++++++++++++++++++- 4 files changed, 184 insertions(+), 16 deletions(-) (limited to 'xml/src') diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java index c071899..4e689fb 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java @@ -150,11 +150,6 @@ public class AttrImpl extends NodeImpl implements Attr { } @Override - public void setNodeValue(String value) throws DOMException { - setValue(value); - } - - @Override public void setPrefix(String prefix) { this.prefix = validatePrefix(prefix, namespaceAware, namespaceURI); } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java index 57ff7dc..13e6c9f 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java @@ -17,11 +17,13 @@ package org.apache.harmony.xml.dom; import org.w3c.dom.Attr; +import org.w3c.dom.CharacterData; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.w3c.dom.ProcessingInstruction; import org.w3c.dom.UserDataHandler; /** @@ -135,7 +137,35 @@ public abstract class NodeImpl implements Node { throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); } - public void setNodeValue(String nodeValue) throws DOMException { + public final void setNodeValue(String nodeValue) throws DOMException { + switch (getNodeType()) { + case CDATA_SECTION_NODE: + case COMMENT_NODE: + case TEXT_NODE: + ((CharacterData) this).setData(nodeValue); + return; + + case PROCESSING_INSTRUCTION_NODE: + ((ProcessingInstruction) this).setData(nodeValue); + return; + + case ATTRIBUTE_NODE: + ((Attr) this).setValue(nodeValue); + return; + + case ELEMENT_NODE: + case ENTITY_REFERENCE_NODE: + case ENTITY_NODE: + case DOCUMENT_NODE: + case DOCUMENT_TYPE_NODE: + case DOCUMENT_FRAGMENT_NODE: + case NOTATION_NODE: + return; // do nothing! + + default: + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, + "Unsupported node type " + getNodeType()); + } } public void setPrefix(String prefix) throws DOMException { @@ -259,7 +289,7 @@ public abstract class NodeImpl implements Node { } } - public void setTextContent(String textContent) throws DOMException { + public final void setTextContent(String textContent) throws DOMException { switch (getNodeType()) { case DOCUMENT_TYPE_NODE: case DOCUMENT_NODE: diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java index 3905865..5c9d123 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java @@ -46,11 +46,6 @@ public class TextImpl extends CharacterDataImpl implements Text { return Node.TEXT_NODE; } - @Override - public String getNodeValue() { - return getData(); - } - public Text splitText(int offset) throws DOMException { Text newText = getOwnerDocument().createTextNode( substringData(offset, getLength() - offset)); diff --git a/xml/src/test/java/tests/xml/DomTest.java b/xml/src/test/java/tests/xml/DomTest.java index d6031ed..566b1f0 100644 --- a/xml/src/test/java/tests/xml/DomTest.java +++ b/xml/src/test/java/tests/xml/DomTest.java @@ -20,17 +20,27 @@ import junit.framework.TestCase; import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; import org.w3c.dom.Comment; +import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.DocumentType; import org.w3c.dom.Element; import org.w3c.dom.Entity; +import org.w3c.dom.EntityReference; import org.w3c.dom.Node; +import org.w3c.dom.Notation; import org.w3c.dom.ProcessingInstruction; import org.w3c.dom.Text; import org.xml.sax.InputSource; +import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; import java.io.StringReader; +import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -40,9 +50,13 @@ import java.util.List; */ public class DomTest extends TestCase { + private Transformer transformer; + private DocumentBuilder builder; + private final String xml = "" + + " " + "]>" + "\n" + " \n" @@ -63,6 +77,7 @@ public class DomTest extends TestCase { private Document document; private DocumentType doctype; private Entity sp; + private Notation png; private Element menu; private Element item; private Attr itemXmlns; @@ -76,7 +91,7 @@ public class DomTest extends TestCase { private Text descriptionText3; private Element option1; private Element option2; - private Node option2Reference; // Text on RI, EntityReference on Dalvik + private Node option2Reference; // resolved to Text on RI, an EntityReference on Dalvik private ProcessingInstruction wafflemaker; private Element nutrition; private Element vitamins; @@ -84,21 +99,24 @@ public class DomTest extends TestCase { private Comment comment; private Element vitaminc; private Text vitamincText; - private List allNodes; @Override protected void setUp() throws Exception { + transformer = TransformerFactory.newInstance().newTransformer(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); + builder = factory.newDocumentBuilder(); - document = factory.newDocumentBuilder() - .parse(new InputSource(new StringReader(xml))); + document = builder.parse(new InputSource(new StringReader(xml))); // doctype nodes doctype = document.getDoctype(); if (doctype.getEntities() != null) { sp = (Entity) doctype.getEntities().item(0); } + if (doctype.getNotations() != null) { + png = (Notation) doctype.getNotations().item(0); + } // document nodes menu = document.getDocumentElement(); @@ -128,6 +146,9 @@ public class DomTest extends TestCase { if (sp != null) { allNodes.add(sp); } + if (png != null) { + allNodes.add(png); + } allNodes.addAll(Arrays.asList(document, doctype, menu, item, itemXmlns, itemXmlnsA, name, standard, deluxe, description, @@ -144,11 +165,22 @@ public class DomTest extends TestCase { assertNotNull("This implementation does not parse entity declarations", sp); } + /** + * Android's parsed DOM doesn't include notations. These nodes will only be + * tested for implementations that support them. + */ + public void testNotations() { + assertNotNull("This implementation does not parse notations", png); + } + public void testLookupNamespaceURIByPrefix() { assertEquals(null, doctype.lookupNamespaceURI("a")); if (sp != null) { assertEquals(null, sp.lookupNamespaceURI("a")); } + if (png != null) { + assertEquals(null, png.lookupNamespaceURI("a")); + } assertEquals(null, document.lookupNamespaceURI("a")); assertEquals(null, menu.lookupNamespaceURI("a")); assertEquals("http://addons", item.lookupNamespaceURI("a")); @@ -179,6 +211,9 @@ public class DomTest extends TestCase { if (sp != null) { assertEquals(null, sp.lookupNamespaceURI(null)); } + if (png != null) { + assertEquals(null, png.lookupNamespaceURI(null)); + } assertEquals(null, menu.lookupNamespaceURI(null)); assertEquals("http://food", item.lookupNamespaceURI(null)); assertEquals("http://food", itemXmlns.lookupNamespaceURI(null)); @@ -214,6 +249,9 @@ public class DomTest extends TestCase { if (sp != null) { assertEquals(null, sp.lookupPrefix("http://addons")); } + if (png != null) { + assertEquals(null, png.lookupPrefix("http://addons")); + } assertEquals(null, menu.lookupPrefix("http://addons")); assertEquals("a", item.lookupPrefix("http://addons")); assertEquals("a", itemXmlns.lookupPrefix("http://addons")); @@ -255,6 +293,9 @@ public class DomTest extends TestCase { if (sp != null) { assertEquals(null, sp.lookupPrefix("http://usda")); } + if (png != null) { + assertEquals(null, png.lookupPrefix("http://usda")); + } assertEquals(null, menu.lookupPrefix("http://usda")); assertEquals(null, item.lookupPrefix("http://usda")); assertEquals(null, itemXmlns.lookupPrefix("http://usda")); @@ -277,4 +318,111 @@ public class DomTest extends TestCase { assertEquals("a", vitaminc.lookupPrefix("http://usda")); assertEquals("a", vitamincText.lookupPrefix("http://usda")); } + + public void testDoctypeSetTextContent() throws TransformerException { + String original = domToString(document); + doctype.setTextContent("foobar"); // strangely, this is specified to no-op + assertEquals(original, domToString(document)); + } + + public void testDocumentSetTextContent() throws TransformerException { + String original = domToString(document); + document.setTextContent("foobar"); // strangely, this is specified to no-op + assertEquals(original, domToString(document)); + } + + public void testElementSetTextContent() throws TransformerException { + String original = domToString(document); + nutrition.setTextContent("foobar"); + String expected = original.replaceFirst( + "(?s).*", "foobar"); + assertEquals(expected, domToString(document)); + } + + public void testEntitySetTextContent() throws TransformerException { + if (sp == null) { + return; + } + try { + sp.setTextContent("foobar"); + fail(); // is this implementation-specific behaviour? + } catch (DOMException e) { + } + } + + public void testNotationSetTextContent() throws TransformerException { + if (png == null) { + return; + } + String original = domToString(document); + png.setTextContent("foobar"); + String expected = original.replace("image/png", "foobar"); + assertEquals(expected, domToString(document)); + } + + /** + * Tests setTextContent on entity references. Although the other tests can + * act on a parsed DOM, this needs to use a programmatically constructed DOM + * because the parser may have replaced the entity reference with the + * corresponding text. + */ + public void testEntityReferenceSetTextContent() throws TransformerException { + document = builder.newDocument(); + Element root = document.createElement("menu"); + document.appendChild(root); + + EntityReference entityReference = document.createEntityReference("sp"); + entityReference.setNodeValue("Maple Syrup"); + root.appendChild(entityReference); + + try { + entityReference.setTextContent("Lite Syrup"); + fail(); + } catch (DOMException e) { + } + } + + public void testAttributeSetTextContent() throws TransformerException { + String original = domToString(document); + standard.setTextContent("foobar"); + String expected = original.replaceFirst( + "standard=\"strawberry\"", "standard=\"foobar\""); + assertEquals(expected, domToString(document)); + } + + public void testTextSetTextContent() throws TransformerException { + String original = domToString(document); + descriptionText1.setTextContent("foobar"); + String expected = original.replace(">Belgianfoobar", " foobar?>"); + assertEquals(expected, domToString(document)); + } + + public void testCommentSetTextContent() throws TransformerException { + String original = domToString(document); + comment.setTextContent("foobar"); + String expected = original.replace("-- add other vitamins? --", "--foobar--"); + assertEquals(expected, domToString(document)); + } + + private String domToString(Document document) + throws TransformerException { + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(document), new StreamResult(writer)); + return writer.toString(); + } } -- cgit v1.1 From 35d7c089bd45f1030407b9b69b46e66f02c03043 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Sat, 20 Feb 2010 10:20:55 -0800 Subject: More XML DOM v3 APIs. This adds the following APIs and tests: - Node.isDefaultNamespace - DomImplementation.hasFeature - Node.isSupported - Node.getFeature - Node.isEqualNode --- .../harmony/xml/dom/DOMImplementationImpl.java | 23 ++- .../org/apache/harmony/xml/dom/DocumentImpl.java | 5 + .../java/org/apache/harmony/xml/dom/NodeImpl.java | 115 +++++++++++- xml/src/test/java/tests/xml/DomTest.java | 195 +++++++++++++++++++++ 4 files changed, 324 insertions(+), 14 deletions(-) (limited to 'xml/src') diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java index 861f0a3..834cc47 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java @@ -50,17 +50,24 @@ public class DOMImplementationImpl implements DOMImplementation { } public boolean hasFeature(String feature, String version) { - // We claim to support DOM Core Level 1 & 2, nothing else. + boolean anyVersion = version == null || version.length() == 0; + if (feature.startsWith("+")) { + feature = feature.substring(1); + } - // TODO + // TODO: fully implement these APIs: + // "LS" (org.w3c.dom.ls) versions "3.0" + // "ElementTraversal" (org.w3c.dom.traversal) versions "1.0" - if ("Core".equalsIgnoreCase(feature) || "XML".equalsIgnoreCase(feature)) { - if (version == null || "".equals(version) || "1.0".equals(version) || "2.0".equals(version)) { - return true; - } + if (feature.equalsIgnoreCase("Core")) { + return anyVersion || version.equals("1.0") || version.equals("2.0") || version.equals("3.0"); + } else if (feature.equalsIgnoreCase("XML")) { + return anyVersion || version.equals("1.0") || version.equals("2.0") || version.equals("3.0"); + } else if (feature.equalsIgnoreCase("XMLVersion")) { + return anyVersion || version.equals("1.0") || version.equals("1.1"); + } else { + return false; } - - return false; } /** diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java index d6d412b..c8819cb 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java @@ -100,6 +100,8 @@ public class DocumentImpl extends InnerNodeImpl implements Document { * @return The new node. */ Node cloneNode(Node node, boolean deep) throws DOMException { + // TODO: callback the UserDataHandler with a NODE_CLONED event + Node target; switch (node.getNodeType()) { @@ -279,6 +281,7 @@ public class DocumentImpl extends InnerNodeImpl implements Document { } public Node importNode(Node importedNode, boolean deep) throws DOMException { + // TODO: callback the UserDataHandler with a NODE_IMPORTED event return cloneNode(importedNode, deep); } @@ -341,6 +344,7 @@ public class DocumentImpl extends InnerNodeImpl implements Document { } public Node adoptNode(Node source) throws DOMException { + // TODO: callback the UserDataHandler with a NODE_ADOPTED event throw new UnsupportedOperationException(); // TODO } @@ -354,6 +358,7 @@ public class DocumentImpl extends InnerNodeImpl implements Document { public Node renameNode(Node n, String namespaceURI, String qualifiedName) throws DOMException { + // TODO: callback the UserDataHandler with a NODE_RENAMED event throw new UnsupportedOperationException(); // TODO } } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java index 13e6c9f..ebfdd52 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java @@ -20,12 +20,16 @@ import org.w3c.dom.Attr; import org.w3c.dom.CharacterData; import org.w3c.dom.DOMException; 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; import org.w3c.dom.UserDataHandler; +import java.util.ArrayList; +import java.util.List; + /** * A straightforward implementation of the corresponding W3C DOM node. * @@ -435,8 +439,11 @@ public abstract class NodeImpl implements Node { return uri.equals(actual); } - public boolean isDefaultNamespace(String namespaceURI) { - throw new UnsupportedOperationException(); // TODO + public final boolean isDefaultNamespace(String namespaceURI) { + String actual = lookupNamespaceURI(null); // null yields the default namespace + return namespaceURI == null + ? actual == null + : namespaceURI.equals(actual); } public final String lookupNamespaceURI(String prefix) { @@ -476,12 +483,108 @@ public abstract class NodeImpl implements Node { return null; } - public boolean isEqualNode(Node arg) { - throw new UnsupportedOperationException(); // TODO + /** + * Returns a list of objects such that two nodes are equal if their lists + * are equal. Be careful: the lists may contain NamedNodeMaps and Nodes, + * neither of which override Object.equals(). Such values must be compared + * manually. + */ + private static List createEqualityKey(Node node) { + List values = new ArrayList(); + values.add(node.getNodeType()); + values.add(node.getNodeName()); + values.add(node.getLocalName()); + values.add(node.getNamespaceURI()); + values.add(node.getPrefix()); + values.add(node.getNodeValue()); + for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { + values.add(child); + } + + switch (node.getNodeType()) { + case DOCUMENT_TYPE_NODE: + DocumentTypeImpl doctype = (DocumentTypeImpl) node; + values.add(doctype.getPublicId()); + values.add(doctype.getSystemId()); + values.add(doctype.getInternalSubset()); + values.add(doctype.getEntities()); + values.add(doctype.getNotations()); + break; + + case ELEMENT_NODE: + Element element = (Element) node; + values.add(element.getAttributes()); + break; + } + + return values; } - public Object getFeature(String feature, String version) { - throw new UnsupportedOperationException(); // TODO + public final boolean isEqualNode(Node arg) { + if (arg == this) { + return true; + } + + List listA = createEqualityKey(this); + List listB = createEqualityKey(arg); + + if (listA.size() != listB.size()) { + return false; + } + + for (int i = 0; i < listA.size(); i++) { + Object a = listA.get(i); + Object b = listB.get(i); + + if (a == b) { + continue; + + } else if (a == null || b == null) { + return false; + + } else if (a instanceof String || a instanceof Short) { + if (!a.equals(b)) { + return false; + } + + } else if (a instanceof NamedNodeMap) { + if (!(b instanceof NamedNodeMap) + || !namedNodeMapsEqual((NamedNodeMap) a, (NamedNodeMap) b)) { + return false; + } + + } else if (a instanceof Node) { + if (!(b instanceof Node) + || !((Node) a).isEqualNode((Node) b)) { + return false; + } + + } else { + throw new AssertionError(); // unexpected type + } + } + + return true; + } + + private boolean namedNodeMapsEqual(NamedNodeMap a, NamedNodeMap b) { + if (a.getLength() != b.getLength()) { + return false; + } + for (int i = 0; i < a.getLength(); i++) { + Node aNode = a.item(i); + Node bNode = aNode.getLocalName() == null + ? b.getNamedItem(aNode.getNodeName()) + : b.getNamedItemNS(aNode.getNamespaceURI(), aNode.getLocalName()); + if (bNode == null || !aNode.isEqualNode(bNode)) { + return false; + } + } + return true; + } + + public final Object getFeature(String feature, String version) { + return isSupported(feature, version) ? this : null; } public Object setUserData(String key, Object data, diff --git a/xml/src/test/java/tests/xml/DomTest.java b/xml/src/test/java/tests/xml/DomTest.java index 566b1f0..5f0a19a 100644 --- a/xml/src/test/java/tests/xml/DomTest.java +++ b/xml/src/test/java/tests/xml/DomTest.java @@ -21,6 +21,7 @@ import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; import org.w3c.dom.Comment; import org.w3c.dom.DOMException; +import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.DocumentType; import org.w3c.dom.Element; @@ -52,6 +53,7 @@ public class DomTest extends TestCase { private Transformer transformer; private DocumentBuilder builder; + private DOMImplementation domImplementation; private final String xml = "