diff options
author | Jesse Wilson <jessewilson@google.com> | 2010-12-20 11:51:41 -0800 |
---|---|---|
committer | Jesse Wilson <jessewilson@google.com> | 2010-12-20 12:38:23 -0800 |
commit | 38e84b835c2101206d846f7ab6fc444914661753 (patch) | |
tree | 67761c4da9cdce3b9fda132ea9196973b6aeb32a | |
parent | 19b9b8115e2946ffbf68148d8755a76b37b082e5 (diff) | |
download | libcore-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.java | 51 | ||||
-rw-r--r-- | luni/src/test/java/libcore/xml/PullParserTest.java | 9 | ||||
-rw-r--r-- | xml/src/main/java/org/kxml2/io/KXmlParser.java | 48 |
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); |