1838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson/* 2838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Copyright (C) 2010 The Android Open Source Project 3838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * 4838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * you may not use this file except in compliance with the License. 6838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * You may obtain a copy of the License at 7838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * 8838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * 10838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * See the License for the specific language governing permissions and 14838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * limitations under the License. 15838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson */ 16838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 17838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilsonpackage libcore.xml; 18838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 19838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilsonimport java.io.StringReader; 2076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilsonimport java.util.Arrays; 21838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilsonimport junit.framework.TestCase; 22838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilsonimport org.xmlpull.v1.XmlPullParser; 23838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilsonimport org.xmlpull.v1.XmlPullParserException; 24838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 25838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson/** 26838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Test doctype handling in pull parsers. 27838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson */ 28838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilsonpublic abstract class PullParserDtdTest extends TestCase { 29838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 3076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private static final int READ_BUFFER_SIZE = 8192; 3176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 32838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson /** 33838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Android's Expat pull parser permits parameter entities to be declared, 34838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * but it doesn't permit such entities to be used. 35838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson */ 36838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testDeclaringParameterEntities() throws Exception { 37838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [" 38838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY % a \"android\">" 39838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]><foo></foo>"; 40838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 41838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson while (parser.next() != XmlPullParser.END_DOCUMENT) { 42838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 43838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 44838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 45838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testUsingParameterEntitiesInDtds() throws Exception { 46995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson assertParseFailure("<!DOCTYPE foo [" 47838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY % a \"android\">" 48838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY b \"%a;\">" 49995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson + "]><foo></foo>"); 50838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 51838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 52838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testUsingParameterInDocuments() throws Exception { 53995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson assertParseFailure("<!DOCTYPE foo [" 54838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY % a \"android\">" 55995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson + "]><foo>&a;</foo>"); 56838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 57838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 5876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson public void testGeneralAndParameterEntityWithTheSameName() throws Exception { 5976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson String xml = "<!DOCTYPE foo [" 6076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ENTITY a \"aaa\">" 6176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ENTITY % a \"bbb\">" 6276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "]><foo>&a;</foo>"; 6376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson XmlPullParser parser = newPullParser(xml); 6476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 6576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 6676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("aaa", parser.getText()); 6776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 6876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 6976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 7076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 71838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testInternalEntities() throws Exception { 72838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [" 73838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY a \"android\">" 74838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]><foo>&a;</foo>"; 75838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 76838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 77838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 78838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("android", parser.getText()); 79838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 80838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 81838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 82838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 83838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testExternalDtdIsSilentlyIgnored() throws Exception { 84838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo SYSTEM \"http://127.0.0.1:1/no-such-file.dtd\"><foo></foo>"; 85838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 86838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 87838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 88838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 89838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 90838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 91838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 92838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 93838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testExternalAndInternalDtd() throws Exception { 94838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo SYSTEM \"http://127.0.0.1:1/no-such-file.dtd\" [" 95838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY a \"android\">" 96838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]><foo>&a;</foo>"; 97838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 98838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 99838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 100838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("android", parser.getText()); 101838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 102838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 103838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 104838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 105838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testInternalEntitiesAreParsed() throws Exception { 106838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [" 107838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY a \"&#65;\">" // & expands to '&', A expands to 'A' 108838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]><foo>&a;</foo>"; 109838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 110838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 111838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 112838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("A", parser.getText()); 113838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 114838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 115838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 116838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 117838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testFoolishlyRecursiveInternalEntities() throws Exception { 118838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [" 119838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY a \"&#38;#38;#38;\">" // expand & to '&' only twice 120838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]><foo>&a;</foo>"; 121838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 122838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 123838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 124838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("&#38;", parser.getText()); 125838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 126838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 127838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 128838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 129838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson /** 1307fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Test that the output of {@code &} is parsed, but {@code &} isn't. 1317fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * http://www.w3.org/TR/2008/REC-xml-20081126/#sec-entexpand 1327fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson */ 1337fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson public void testExpansionOfEntityAndCharacterReferences() throws Exception { 1347fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson String xml = "<!DOCTYPE foo [" 1357fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson + "<!ENTITY example \"<p>An ampersand (&#38;) may be escaped\n" 1367fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson + "numerically (&#38;#38;) or with a general entity\n" 1377fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson + "(&amp;).</p>\" >" 1387fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson + "]><foo>&example;</foo>"; 1397fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson XmlPullParser parser = newPullParser(xml); 1407fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 1417fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 1427fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals("p", parser.getName()); 1437fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 1447fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals("An ampersand (&) may be escaped\n" 1457fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson + "numerically (&) or with a general entity\n" 1467fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson + "(&).", parser.getText()); 1477fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 1487fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals("p", parser.getName()); 1497fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 1507fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 1517fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 1527fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 1537fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson public void testGeneralEntitiesAreStoredUnresolved() throws Exception { 1547fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson String xml = "<!DOCTYPE foo [" 1557fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson + "<!ENTITY b \"&a;\" >" 1567fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson + "<!ENTITY a \"android\" >" 1577fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson + "]><foo>&a;</foo>"; 1587fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson XmlPullParser parser = newPullParser(xml); 1597fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 1607fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 1617fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals("android", parser.getText()); 1627fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 1637fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 1647fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 1657fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 16638e84b835c2101206d846f7ab6fc444914661753Jesse Wilson public void testStructuredEntityAndNextToken() throws Exception { 16738e84b835c2101206d846f7ab6fc444914661753Jesse Wilson String xml = "<!DOCTYPE foo [<!ENTITY bb \"<bar>baz<!--quux--></bar>\">]><foo>a&bb;c</foo>"; 16838e84b835c2101206d846f7ab6fc444914661753Jesse Wilson XmlPullParser parser = newPullParser(xml); 16938e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.DOCDECL, parser.nextToken()); 17038e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.nextToken()); 17138e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("foo", parser.getName()); 17238e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.nextToken()); 17338e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("a", parser.getText()); 17438e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken()); 17538e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("bb", parser.getName()); 17638e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("", parser.getText()); 17738e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.nextToken()); 17838e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("bar", parser.getName()); 17938e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.nextToken()); 18038e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("baz", parser.getText()); 18138e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.COMMENT, parser.nextToken()); 18238e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("quux", parser.getText()); 18338e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.nextToken()); 18438e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("bar", parser.getName()); 18538e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.nextToken()); 18638e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("c", parser.getText()); 18738e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 18838e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 18938e84b835c2101206d846f7ab6fc444914661753Jesse Wilson } 19038e84b835c2101206d846f7ab6fc444914661753Jesse Wilson 1917fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson /** 192838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Android's Expat replaces external entities with the empty string. 193838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson */ 194838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testUsingExternalEntities() throws Exception { 195838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [" 196838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY a SYSTEM \"http://localhost:1/no-such-file.xml\">" 197838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]><foo>&a;</foo>"; 198838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 199838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 200838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson // &a; is dropped! 201838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 202838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 203838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 204838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 205773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson /** 206773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * Android's ExpatPullParser replaces missing entities with the empty string 207773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * when an external DTD is declared. 208773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson */ 209773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson public void testExternalDtdAndMissingEntity() throws Exception { 210773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson String xml = "<!DOCTYPE foo SYSTEM \"http://127.0.0.1:1/no-such-file.dtd\">" 211773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson + "<foo>&a;</foo>"; 212773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson XmlPullParser parser = newPullParser(xml); 213773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 214773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 215773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 216773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson } 217773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson 218773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson 219838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testExternalIdIsCaseSensitive() throws Exception { 220838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson // The spec requires 'SYSTEM' in upper case 221995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson assertParseFailure("<!DOCTYPE foo [" 222838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY a system \"http://localhost:1/no-such-file.xml\">" 223995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson + "]><foo/>"); 224838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 225838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 226838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson /** 227838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Use a DTD to specify that {@code <foo>} only contains {@code <bar>} tags. 228838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Validating parsers react to this by dropping whitespace between the two 229838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * tags. 230838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson */ 231838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testDtdDoesNotInformIgnorableWhitespace() throws Exception { 232838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [\n" 233838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT foo (bar)*>\n" 234838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT bar ANY>\n" 235838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]>" 236838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "<foo> \n <bar></bar> \t </foo>"; 237838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 238838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 239838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 240838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 241838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(" \n ", parser.getText()); 242838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 243838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("bar", parser.getName()); 244838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 245838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("bar", parser.getName()); 246838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 247838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(" \t ", parser.getText()); 248838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 249838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 250838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 251838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 252838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testEmptyDoesNotInformIgnorableWhitespace() throws Exception { 253838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [\n" 254838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT foo EMPTY>\n" 255838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]>" 256838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "<foo> \n </foo>"; 257838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 258838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 259838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 260838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 261838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(" \n ", parser.getText()); 262838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 263838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 264838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 265838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 266838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson /** 267838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Test that the parser doesn't expand the entity attributes. 268838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson */ 269838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testAttributeOfTypeEntity() throws Exception { 270838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [\n" 271838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY a \"android\">" 272838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT foo ANY>\n" 273838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ATTLIST foo\n" 274838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " bar ENTITY #IMPLIED>" 275838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]>" 276838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "<foo bar=\"a\"></foo>"; 277838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 278838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 279838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 280838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("a", parser.getAttributeValue(null, "bar")); 281838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 282838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 283838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 284838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 285838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testTagStructureNotValidated() throws Exception { 286838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [\n" 287838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT foo (bar)*>\n" 288838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT bar ANY>\n" 289838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT baz ANY>\n" 290838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]>" 291838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "<foo><bar/><bar/><baz/></foo>"; 292838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 293838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 294838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 295838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 296838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("bar", parser.getName()); 297838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 298838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 299838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("bar", parser.getName()); 300838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 301838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 302838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("baz", parser.getName()); 303838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 304838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 305838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 306838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 307838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 308838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testAttributeDefaultValues() throws Exception { 309838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [\n" 31076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ATTLIST bar\n" 31176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " baz (a|b|c) \"c\">" 31276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "]>" 31376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "<foo>" 31476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "<bar/>" 31576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "<bar baz=\"a\"/>" 31676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "</foo>"; 31776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson XmlPullParser parser = newPullParser(xml); 31876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 31976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 32076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("bar", parser.getName()); 32176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("c", parser.getAttributeValue(null, "baz")); 32276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 32376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 32476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("bar", parser.getName()); 32576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("a", parser.getAttributeValue(null, "baz")); 32676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 32776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 32876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 32976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 33076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 33176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson public void testAttributeDefaultValueEntitiesExpanded() throws Exception { 33276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson String xml = "<!DOCTYPE foo [\n" 33376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ENTITY g \"ghi\">" 334838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT foo ANY>\n" 335838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ATTLIST foo\n" 33676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " bar CDATA \"abc & def &g; jk\">" 337838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]>" 338838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "<foo></foo>"; 339838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 340838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 341838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 34276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("abc & def ghi jk", parser.getAttributeValue(null, "bar")); 34376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 34476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 34576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 34676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 34776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson public void testAttributeDefaultValuesAndNamespaces() throws Exception { 34876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson String xml = "<!DOCTYPE foo [\n" 34976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ATTLIST foo\n" 35076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " bar:a CDATA \"android\">" 35176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "]>" 35276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "<foo xmlns:bar='http://bar'></foo>"; 35376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson XmlPullParser parser = newPullParser(xml); 35476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); 35576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 35676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("foo", parser.getName()); 35776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson // In Expat, namespaces don't apply to default attributes 35876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson int index = indexOfAttributeWithName(parser, "bar:a"); 35976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("", parser.getAttributeNamespace(index)); 36076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("bar:a", parser.getAttributeName(index)); 36176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("android", parser.getAttributeValue(index)); 36276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("CDATA", parser.getAttributeType(index)); 363838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 36476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 36576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 36676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 36776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private int indexOfAttributeWithName(XmlPullParser parser, String name) { 36876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson for (int i = 0; i < parser.getAttributeCount(); i++) { 36976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (parser.getAttributeName(i).equals(name)) { 37076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return i; 37176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 37276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 37376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return -1; 37476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 37576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 37676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson public void testAttributeEntitiesExpandedEagerly() throws Exception { 377995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson assertParseFailure("<!DOCTYPE foo [\n" 37876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ELEMENT foo ANY>\n" 37976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ATTLIST foo\n" 38076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " bar CDATA \"abc & def &g; jk\">" 38176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ENTITY g \"ghi\">" 38276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "]>" 383995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson + "<foo></foo>"); 384838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 385838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 386838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testRequiredAttributesOmitted() throws Exception { 387838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [\n" 388838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT foo ANY>\n" 389838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ATTLIST foo\n" 390838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " bar (a|b|c) #REQUIRED>" 391838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]>" 392838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "<foo></foo>"; 393838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 394838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 395838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 396838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(null, parser.getAttributeValue(null, "bar")); 397838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 398838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 399838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 400838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testFixedAttributesWithConflictingValues() throws Exception { 401838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [\n" 402838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ELEMENT foo ANY>\n" 403838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ATTLIST foo\n" 404838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " bar (a|b|c) #FIXED \"c\">" 405838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]>" 406838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "<foo bar=\"a\"></foo>"; 407838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 408838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 409838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 410838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("a", parser.getAttributeValue(null, "bar")); 411838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 412838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 413838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 414838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testParsingNotations() throws Exception { 415838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [\n" 416838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!NOTATION type-a PUBLIC \"application/a\"> \n" 417838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!NOTATION type-b PUBLIC \"image/b\">\n" 418838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!NOTATION type-c PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n" 419838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"> \n" 420838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY file SYSTEM \"d.xml\">\n" 421838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!ENTITY fileWithNdata SYSTEM \"e.bin\" NDATA type-b>\n" 422838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]>" 423838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "<foo type=\"type-a\"/>"; 424838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 425838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 426838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 427838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 428838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 429838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 430838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testCommentsInDoctype() throws Exception { 431838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [" 432838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + " <!-- ' -->" 433838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson + "]><foo>android</foo>"; 434838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 435838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 436838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 437838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("android", parser.getText()); 438838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 439838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 440838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 441838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 442838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testDoctypeNameOnly() throws Exception { 443838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo><foo></foo>"; 444838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 445838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 446838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 447838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 448838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals("foo", parser.getName()); 449838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 450838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 451838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 45276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson public void testVeryLongEntities() throws Exception { 45376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson String a = repeat('a', READ_BUFFER_SIZE + 1); 45476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson String b = repeat('b', READ_BUFFER_SIZE + 1); 45576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson String c = repeat('c', READ_BUFFER_SIZE + 1); 45676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 45776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson String xml = "<!DOCTYPE foo [\n" 45876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ENTITY " + a + " \"d &" + b + "; e\">" 45976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + " <!ENTITY " + b + " \"f " + c + " g\">" 46076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "]>" 46176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson + "<foo>h &" + a + "; i</foo>"; 46276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson XmlPullParser parser = newPullParser(xml); 46376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 46476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 46576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals("h d f " + c + " g e i", parser.getText()); 46676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 46776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 46876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 46976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 47076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson public void testManuallyRegisteredEntitiesWithDoctypeParsing() throws Exception { 47176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson String xml = "<foo>&a;</foo>"; 47276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson XmlPullParser parser = newPullParser(xml); 47376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson try { 47476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson parser.defineEntityReplacementText("a", "android"); 47576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson fail(); 47676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } catch (UnsupportedOperationException expected) { 47776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } catch (IllegalStateException expected) { 47876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 47976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 48076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 481838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson public void testDoctypeWithNextToken() throws Exception { 482838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson String xml = "<!DOCTYPE foo [<!ENTITY bb \"bar baz\">]><foo>a&bb;c</foo>"; 483838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser parser = newPullParser(xml); 484838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.DOCDECL, parser.nextToken()); 485838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(" foo [<!ENTITY bb \"bar baz\">]", parser.getText()); 486838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertNull(parser.getName()); 487838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.nextToken()); 48838e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.TEXT, parser.next()); 48938e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals("abar bazc", parser.getText()); 49038e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 49138e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 49238e84b835c2101206d846f7ab6fc444914661753Jesse Wilson } 49338e84b835c2101206d846f7ab6fc444914661753Jesse Wilson 49438e84b835c2101206d846f7ab6fc444914661753Jesse Wilson public void testDoctypeSpansBuffers() throws Exception { 49538e84b835c2101206d846f7ab6fc444914661753Jesse Wilson char[] doctypeChars = new char[READ_BUFFER_SIZE + 1]; 49638e84b835c2101206d846f7ab6fc444914661753Jesse Wilson Arrays.fill(doctypeChars, 'x'); 49738e84b835c2101206d846f7ab6fc444914661753Jesse Wilson String doctypeBody = " foo [<!--" + new String(doctypeChars) + "-->]"; 49838e84b835c2101206d846f7ab6fc444914661753Jesse Wilson String xml = "<!DOCTYPE" + doctypeBody + "><foo/>"; 49938e84b835c2101206d846f7ab6fc444914661753Jesse Wilson XmlPullParser parser = newPullParser(xml); 50038e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.DOCDECL, parser.nextToken()); 50138e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(doctypeBody, parser.getText()); 50238e84b835c2101206d846f7ab6fc444914661753Jesse Wilson assertEquals(XmlPullParser.START_TAG, parser.next()); 503838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_TAG, parser.next()); 504838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 505838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 506838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 507995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson public void testDoctypeInDocumentElement() throws Exception { 508995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson assertParseFailure("<foo><!DOCTYPE foo></foo>"); 509995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson } 510995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson 511995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson public void testDoctypeAfterDocumentElement() throws Exception { 512995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson assertParseFailure("<foo/><!DOCTYPE foo>"); 513995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson } 514995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson 515995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson private void assertParseFailure(String xml) throws Exception { 516995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson XmlPullParser parser = newPullParser(); 517995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson parser.setInput(new StringReader(xml)); 518838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson try { 519838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson while (parser.next() != XmlPullParser.END_DOCUMENT) { 520838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 521838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson fail(); 522838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } catch (XmlPullParserException expected) { 523838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 524838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 525838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 52676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private String repeat(char c, int length) { 52776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson char[] chars = new char[length]; 52876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson Arrays.fill(chars, c); 52976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return new String(chars); 53076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 53176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 532838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson private XmlPullParser newPullParser(String xml) throws XmlPullParserException { 533838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson XmlPullParser result = newPullParser(); 534838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson result.setInput(new StringReader(xml)); 535838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson return result; 536838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson } 537838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson 538838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson /** 539838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson * Creates a new pull parser. 540838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson */ 54176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson abstract XmlPullParser newPullParser() throws XmlPullParserException; 542838419e39510cb3bf04cf5bfef2929a7cf759e65Jesse Wilson} 543