summaryrefslogtreecommitdiffstats
path: root/xml
diff options
context:
space:
mode:
authorJesse Wilson <jessewilson@google.com>2010-03-19 12:51:43 -0700
committerJesse Wilson <jessewilson@google.com>2010-03-19 13:37:36 -0700
commit4a5c3fdcab5bffc6b8258c8029b02d97b0dd3f9d (patch)
treeca0db7f6200f13a37b0e186106bbdd1e158eeaff /xml
parent0bd7c8e0333e2e641d1b0a1fafc0e07d0defa761 (diff)
downloadlibcore-4a5c3fdcab5bffc6b8258c8029b02d97b0dd3f9d.zip
libcore-4a5c3fdcab5bffc6b8258c8029b02d97b0dd3f9d.tar.gz
libcore-4a5c3fdcab5bffc6b8258c8029b02d97b0dd3f9d.tar.bz2
Fixing namespace+prefix mode in Expat and removing optional fields from callbacks.
The first part is related to bug 6632: http://code.google.com/p/android/issues/detail?id=6632 I added these optional fields back when I was originally updating the XML parser for Froyo. I've decided to remove them to simplify migrating between Android and the RI. It should also save some object allocations. Note that the RI v5 and the RI v6 behave differently for optional values on attributes; this motivated me to add the otherwise unfortunate assertOneOf() method to the testcase. (We behave more like RI v6, which is to supply the values upon request) Change-Id: Icfa5d29976a86bf194b3ed7c0d9e2275c3bff9dd
Diffstat (limited to 'xml')
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/ExpatReader.java2
-rw-r--r--xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp4
-rw-r--r--xml/src/test/java/tests/xml/AllTests.java1
-rw-r--r--xml/src/test/java/tests/xml/SaxTest.java175
4 files changed, 179 insertions, 3 deletions
diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java b/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java
index dbe3a3a..d187456 100644
--- a/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java
+++ b/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java
@@ -244,7 +244,7 @@ public class ExpatReader implements XMLReader {
}
public void parse(InputSource input) throws IOException, SAXException {
- if (processNamespacePrefixes == processNamespaces) {
+ if (processNamespacePrefixes && processNamespaces) {
/*
* Expat has XML_SetReturnNSTriplet, but that still doesn't
* include xmlns attributes like this feature requires. We may
diff --git a/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 4721800..b893309 100644
--- a/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -628,8 +628,8 @@ static void startElement(void* data, const char* elementName,
jobject javaParser = parsingContext->object;
ExpatElementName e(env, parsingContext, elementName);
- jstring uri = e.uri();
- jstring localName = e.localName();
+ jstring uri = parsingContext->processNamespaces ? e.uri() : emptyString;
+ jstring localName = parsingContext->processNamespaces ? e.localName() : emptyString;
jstring qName = e.qName();
stringStackPush(parsingContext, qName);
diff --git a/xml/src/test/java/tests/xml/AllTests.java b/xml/src/test/java/tests/xml/AllTests.java
index 96b96c5..e9f833f 100644
--- a/xml/src/test/java/tests/xml/AllTests.java
+++ b/xml/src/test/java/tests/xml/AllTests.java
@@ -30,6 +30,7 @@ public class AllTests {
suite.addTestSuite(SimpleBuilderTest.class);
suite.addTestSuite(NodeTest.class);
suite.addTestSuite(NormalizeTest.class);
+ suite.addTestSuite(SaxTest.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/SaxTest.java b/xml/src/test/java/tests/xml/SaxTest.java
new file mode 100644
index 0000000..2c75a73
--- /dev/null
+++ b/xml/src/test/java/tests/xml/SaxTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Initiate and observe a SAX parse session.
+ */
+public class SaxTest extends TestCase {
+
+ public void testNoPrefixesNoNamespaces() throws Exception {
+ parse(false, false, "<foo bar=\"baz\"/>", new DefaultHandler() {
+ @Override public void startElement(String uri, String localName,
+ String qName, Attributes attributes) {
+ assertEquals("", uri);
+ assertEquals("", localName);
+ assertEquals("foo", qName);
+ assertEquals(1, attributes.getLength());
+ assertEquals("", attributes.getURI(0));
+ assertOneOf("bar", "", attributes.getLocalName(0));
+ assertEquals("bar", attributes.getQName(0));
+ }
+ });
+
+ parse(false, false, "<a:foo a:bar=\"baz\"/>", new DefaultHandler() {
+ @Override public void startElement(String uri, String localName,
+ String qName, Attributes attributes) {
+ assertEquals("", uri);
+ assertEquals("", localName);
+ assertEquals("a:foo", qName);
+ assertEquals(1, attributes.getLength());
+ assertEquals("", attributes.getURI(0));
+ assertOneOf("a:bar", "", attributes.getLocalName(0));
+ assertEquals("a:bar", attributes.getQName(0));
+ }
+ });
+ }
+
+ public void testNoPrefixesYesNamespaces() throws Exception {
+ parse(false, true, "<foo bar=\"baz\"/>", new DefaultHandler() {
+ @Override public void startElement(String uri, String localName,
+ String qName, Attributes attributes) {
+ assertEquals("", uri);
+ assertEquals("foo", localName);
+ assertEquals("foo", qName);
+ assertEquals(1, attributes.getLength());
+ assertEquals("", attributes.getURI(0));
+ assertEquals("bar", attributes.getLocalName(0));
+ assertEquals("bar", attributes.getQName(0));
+ }
+ });
+
+ parse(false, true, "<a:foo a:bar=\"baz\" xmlns:a=\"http://quux\"/>", new DefaultHandler() {
+ @Override public void startElement(String uri, String localName,
+ String qName, Attributes attributes) {
+ assertEquals("http://quux", uri);
+ assertEquals("foo", localName);
+ assertEquals("a:foo", qName);
+ assertEquals(1, attributes.getLength());
+ assertEquals("http://quux", attributes.getURI(0));
+ assertEquals("bar", attributes.getLocalName(0));
+ assertEquals("a:bar", attributes.getQName(0));
+ }
+ });
+ }
+
+ /**
+ * Android's Expat-based SAX parser fails this test because Expat doesn't
+ * supply us with our much desired {@code xmlns="http://..."} attributes.
+ */
+ public void testYesPrefixesYesNamespaces() throws Exception {
+ parse(true, true, "<foo bar=\"baz\"/>", new DefaultHandler() {
+ @Override public void startElement(String uri, String localName,
+ String qName, Attributes attributes) {
+ assertEquals("", uri);
+ assertEquals("foo", localName);
+ assertEquals("foo", qName);
+ assertEquals(1, attributes.getLength());
+ assertEquals("", attributes.getURI(0));
+ assertEquals("bar", attributes.getLocalName(0));
+ assertEquals("bar", attributes.getQName(0));
+ }
+ });
+
+ parse(true, true, "<a:foo a:bar=\"baz\" xmlns:a=\"http://quux\"/>", new DefaultHandler() {
+ @Override public void startElement(String uri, String localName,
+ String qName, Attributes attributes) {
+ assertEquals("http://quux", uri);
+ assertEquals("foo", localName);
+ assertEquals("a:foo", qName);
+ assertEquals(2, attributes.getLength());
+ assertEquals("http://quux", attributes.getURI(0));
+ assertEquals("bar", attributes.getLocalName(0));
+ assertEquals("a:bar", attributes.getQName(0));
+ assertEquals("", attributes.getURI(1));
+ assertEquals("", attributes.getLocalName(1));
+ assertEquals("xmlns:a", attributes.getQName(1));
+ }
+ });
+ }
+
+ public void testYesPrefixesNoNamespaces() throws Exception {
+ parse(true, false, "<foo bar=\"baz\"/>", new DefaultHandler() {
+ @Override public void startElement(String uri, String localName,
+ String qName, Attributes attributes) {
+ assertEquals("", uri);
+ assertEquals("", localName);
+ assertEquals("foo", qName);
+ assertEquals(1, attributes.getLength());
+ assertEquals("", attributes.getURI(0));
+ assertOneOf("bar", "", attributes.getLocalName(0));
+ assertEquals("bar", attributes.getQName(0));
+ }
+ });
+
+ parse(true, false, "<a:foo a:bar=\"baz\"/>", new DefaultHandler() {
+ @Override public void startElement(String uri, String localName,
+ String qName, Attributes attributes) {
+ assertEquals("", uri);
+ assertEquals("", localName);
+ assertEquals("a:foo", qName);
+ assertEquals(1, attributes.getLength());
+ assertEquals("", attributes.getURI(0));
+ assertOneOf("a:bar", "", attributes.getLocalName(0));
+ assertEquals("a:bar", attributes.getQName(0));
+ }
+ });
+ }
+
+ private void parse(boolean prefixes, boolean namespaces, String xml,
+ ContentHandler handler) throws Exception {
+ SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+ XMLReader reader = parser.getXMLReader();
+ reader.setFeature("http://xml.org/sax/features/namespace-prefixes", prefixes);
+ reader.setFeature("http://xml.org/sax/features/namespaces", namespaces);
+ reader.setContentHandler(handler);
+ reader.parse(new InputSource(new StringReader(xml)));
+ }
+
+ /**
+ * @param expected an optional value that may or may have not been supplied
+ * @param sentinel a marker value that means the expected value was omitted
+ */
+ private void assertOneOf(String expected, String sentinel, String actual) {
+ List<String> optionsList = Arrays.asList(sentinel, expected);
+ assertTrue("Expected one of " + optionsList + " but was " + actual,
+ optionsList.contains(actual));
+ }
+}