summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Wilson <jessewilson@google.com>2010-12-20 11:51:41 -0800
committerJesse Wilson <jessewilson@google.com>2010-12-20 12:38:23 -0800
commit38e84b835c2101206d846f7ab6fc444914661753 (patch)
tree67761c4da9cdce3b9fda132ea9196973b6aeb32a
parent19b9b8115e2946ffbf68148d8755a76b37b082e5 (diff)
downloadlibcore-38e84b835c2101206d846f7ab6fc444914661753.zip
libcore-38e84b835c2101206d846f7ab6fc444914661753.tar.gz
libcore-38e84b835c2101206d846f7ab6fc444914661753.tar.bz2
Capture the DTD body while it is being parsed.
Change-Id: Ibef02ca759eb56a00f0f72f4063d129ef5350d21 http://b/3241492
-rw-r--r--luni/src/test/java/libcore/xml/PullParserDtdTest.java51
-rw-r--r--luni/src/test/java/libcore/xml/PullParserTest.java9
-rw-r--r--xml/src/main/java/org/kxml2/io/KXmlParser.java48
3 files changed, 85 insertions, 23 deletions
diff --git a/luni/src/test/java/libcore/xml/PullParserDtdTest.java b/luni/src/test/java/libcore/xml/PullParserDtdTest.java
index 0101d7b..834bf00 100644
--- a/luni/src/test/java/libcore/xml/PullParserDtdTest.java
+++ b/luni/src/test/java/libcore/xml/PullParserDtdTest.java
@@ -168,6 +168,31 @@ public abstract class PullParserDtdTest extends TestCase {
assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
}
+ public void testStructuredEntityAndNextToken() throws Exception {
+ String xml = "<!DOCTYPE foo [<!ENTITY bb \"<bar>baz<!--quux--></bar>\">]><foo>a&bb;c</foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.DOCDECL, parser.nextToken());
+ assertEquals(XmlPullParser.START_TAG, parser.nextToken());
+ assertEquals("foo", parser.getName());
+ assertEquals(XmlPullParser.TEXT, parser.nextToken());
+ assertEquals("a", parser.getText());
+ assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken());
+ assertEquals("bb", parser.getName());
+ assertEquals("", parser.getText());
+ assertEquals(XmlPullParser.START_TAG, parser.nextToken());
+ assertEquals("bar", parser.getName());
+ assertEquals(XmlPullParser.TEXT, parser.nextToken());
+ assertEquals("baz", parser.getText());
+ assertEquals(XmlPullParser.COMMENT, parser.nextToken());
+ assertEquals("quux", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.nextToken());
+ assertEquals("bar", parser.getName());
+ assertEquals(XmlPullParser.TEXT, parser.nextToken());
+ assertEquals("c", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
/**
* Android's Expat replaces external entities with the empty string.
*/
@@ -462,10 +487,6 @@ public abstract class PullParserDtdTest extends TestCase {
}
}
- /**
- * In honeycomb, KxmlParser's DTD handling was improved but no longer
- * supports returning the full DTD text. http://b/3241492
- */
public void testDoctypeWithNextToken() throws Exception {
String xml = "<!DOCTYPE foo [<!ENTITY bb \"bar baz\">]><foo>a&bb;c</foo>";
XmlPullParser parser = newPullParser(xml);
@@ -473,13 +494,21 @@ public abstract class PullParserDtdTest extends TestCase {
assertEquals(" foo [<!ENTITY bb \"bar baz\">]", parser.getText());
assertNull(parser.getName());
assertEquals(XmlPullParser.START_TAG, parser.nextToken());
- assertEquals(XmlPullParser.TEXT, parser.nextToken());
- assertEquals("a", parser.getText());
- assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken());
- assertEquals("bb", parser.getName());
- assertEquals("bar baz", parser.getText());
- assertEquals(XmlPullParser.TEXT, parser.nextToken());
- assertEquals("c", parser.getText());
+ assertEquals(XmlPullParser.TEXT, parser.next());
+ assertEquals("abar bazc", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testDoctypeSpansBuffers() throws Exception {
+ char[] doctypeChars = new char[READ_BUFFER_SIZE + 1];
+ Arrays.fill(doctypeChars, 'x');
+ String doctypeBody = " foo [<!--" + new String(doctypeChars) + "-->]";
+ String xml = "<!DOCTYPE" + doctypeBody + "><foo/>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.DOCDECL, parser.nextToken());
+ assertEquals(doctypeBody, parser.getText());
+ assertEquals(XmlPullParser.START_TAG, parser.next());
assertEquals(XmlPullParser.END_TAG, parser.next());
assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
}
diff --git a/luni/src/test/java/libcore/xml/PullParserTest.java b/luni/src/test/java/libcore/xml/PullParserTest.java
index 2862de0..aaa76a6 100644
--- a/luni/src/test/java/libcore/xml/PullParserTest.java
+++ b/luni/src/test/java/libcore/xml/PullParserTest.java
@@ -615,6 +615,15 @@ public abstract class PullParserTest extends TestCase {
assertEquals(0, parser.getDepth());
}
+ public void testNextAfterEndDocument() throws Exception {
+ XmlPullParser parser = newPullParser();
+ parser.setInput(new StringReader("<foo></foo>"));
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
public void testNamespaces() throws Exception {
String xml = "<one xmlns='ns:default' xmlns:n1='ns:1' a='b'>\n"
+ " <n1:two c='d' n1:e='f' xmlns:n2='ns:2'>text</n1:two>\n"
diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java
index 9fb858b..f9d6461 100644
--- a/xml/src/main/java/org/kxml2/io/KXmlParser.java
+++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java
@@ -110,6 +110,13 @@ public class KXmlParser implements XmlPullParser, Closeable {
private boolean keepNamespaceAttributes;
/**
+ * If non-null, the contents of the read buffer must be copied into this
+ * string builder before the read buffer is overwritten. This is used to
+ * capture the raw DTD text while parsing the DTD.
+ */
+ private StringBuilder bufferCapture;
+
+ /**
* Entities defined in or for this document. This map is created lazily.
*/
private Map<String, char[]> documentEntities;
@@ -408,10 +415,7 @@ public class KXmlParser implements XmlPullParser, Closeable {
}
break;
case DOCDECL:
- readDoctype();
- if (justOneToken) {
- text = ""; // TODO: support capturing the doctype text
- }
+ readDoctype(justOneToken);
break;
default:
@@ -563,16 +567,32 @@ public class KXmlParser implements XmlPullParser, Closeable {
* Read the document's DTD. Although this parser is non-validating, the DTD
* must be parsed to capture entity values and default attribute values.
*/
- private void readDoctype() throws IOException, XmlPullParserException {
+ private void readDoctype(boolean saveDtdText) throws IOException, XmlPullParserException {
read(START_DOCTYPE);
- skip();
- rootElementName = readName();
- readExternalId(true, true);
- skip();
- if (peekCharacter() == '[') {
- readInternalSubset();
+
+ int startPosition = -1;
+ if (saveDtdText) {
+ bufferCapture = new StringBuilder();
+ startPosition = position;
}
- skip();
+ try {
+ skip();
+ rootElementName = readName();
+ readExternalId(true, true);
+ skip();
+ if (peekCharacter() == '[') {
+ readInternalSubset();
+ }
+ skip();
+ } finally {
+ if (saveDtdText) {
+ bufferCapture.append(buffer, 0, position);
+ bufferCapture.delete(0, startPosition);
+ text = bufferCapture.toString();
+ bufferCapture = null;
+ }
+ }
+
read('>');
}
@@ -1456,6 +1476,10 @@ public class KXmlParser implements XmlPullParser, Closeable {
}
}
+ if (bufferCapture != null) {
+ bufferCapture.append(buffer, 0, position);
+ }
+
if (limit != position) {
limit -= position;
System.arraycopy(buffer, position, buffer, 0, limit);