diff options
-rw-r--r-- | luni/src/test/java/org/apache/harmony/xml/PullParserTest.java | 50 | ||||
-rw-r--r-- | xml/src/main/java/org/kxml2/io/KXmlParser.java | 58 |
2 files changed, 78 insertions, 30 deletions
diff --git a/luni/src/test/java/org/apache/harmony/xml/PullParserTest.java b/luni/src/test/java/org/apache/harmony/xml/PullParserTest.java index e0d8996..0ff40f6 100644 --- a/luni/src/test/java/org/apache/harmony/xml/PullParserTest.java +++ b/luni/src/test/java/org/apache/harmony/xml/PullParserTest.java @@ -89,6 +89,15 @@ public abstract class PullParserTest extends TestCase { assertEquals("a", parser.getName()); } + public void testRegularNumericEntities() throws Exception { + XmlPullParser parser = newPullParser(); + parser.setInput(new StringReader("<foo>A</foo>")); + assertEquals(XmlPullParser.START_TAG, parser.next()); + assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken()); + assertEquals("#65", parser.getName()); + assertEquals("A", parser.getText()); + } + public void testNumericEntitiesLargerThanChar() throws Exception { XmlPullParser parser = newPullParser(); parser.setInput(new StringReader( @@ -132,7 +141,7 @@ public abstract class PullParserTest extends TestCase { assertEquals(XmlPullParser.END_TAG, parser.next()); } - public void testOmittedNumericEntities() throws Exception { + public void testOmittedNumericEntities() throws Exception { XmlPullParser parser = newPullParser(); parser.setInput(new StringReader("<foo>&#;</foo>")); assertEquals(XmlPullParser.START_TAG, parser.next()); @@ -220,6 +229,45 @@ public abstract class PullParserTest extends TestCase { assertEquals("yz", parser.getText()); } + public void testMissingEntities() throws Exception { + XmlPullParser parser = newPullParser(); + parser.setInput(new StringReader("<foo>&aaa;</foo>")); + assertEquals(XmlPullParser.START_TAG, parser.next()); + assertNextFails(parser); + } + + public void testMissingEntitiesWithRelaxed() throws Exception { + XmlPullParser parser = newPullParser(); + parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true); + parser.setInput(new StringReader("<foo>&aaa;</foo>")); + assertEquals(XmlPullParser.START_TAG, parser.next()); + assertEquals(XmlPullParser.TEXT, parser.next()); + assertEquals(null, parser.getName()); + assertEquals("&aaa;", parser.getText()); + assertEquals(XmlPullParser.END_TAG, parser.next()); + } + + public void testMissingEntitiesUsingNextToken() throws Exception { + XmlPullParser parser = newPullParser(); + testMissingEntitiesUsingNextToken(parser); + } + + public void testMissingEntitiesUsingNextTokenWithRelaxed() throws Exception { + XmlPullParser parser = newPullParser(); + parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true); + testMissingEntitiesUsingNextToken(parser); + } + + private void testMissingEntitiesUsingNextToken(XmlPullParser parser) + throws XmlPullParserException, IOException { + parser.setInput(new StringReader("<foo>&aaa;</foo>")); + assertEquals(XmlPullParser.START_TAG, parser.nextToken()); + assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken()); + assertEquals("aaa", parser.getName()); + assertEquals(null, parser.getText()); + assertEquals(XmlPullParser.END_TAG, parser.next()); + } + public void testGreaterThanInText() throws Exception { XmlPullParser parser = newPullParser(); parser.setInput(new StringReader("<foo>></foo>")); diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java index 9c20e0d..d3834aa 100644 --- a/xml/src/main/java/org/kxml2/io/KXmlParser.java +++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java @@ -521,15 +521,13 @@ public class KXmlParser implements XmlPullParser { return; } - if (!relaxed) { - if (!name.equals(elementStack[sp + 3])) { - throw new XmlPullParserException( - "expected: /" + elementStack[sp + 3] + " read: " + name, this, null); - } - + if (name.equals(elementStack[sp + 3])) { namespace = elementStack[sp]; prefix = elementStack[sp + 1]; name = elementStack[sp + 2]; + } else if (!relaxed) { + throw new XmlPullParserException( + "expected: /" + elementStack[sp + 3] + " read: " + name, this, null); } } @@ -705,6 +703,7 @@ public class KXmlParser implements XmlPullParser { int c = peekCharacter(); if (c == ';') { + out.append(';'); position++; break; @@ -727,35 +726,36 @@ public class KXmlParser implements XmlPullParser { } } - String code = out.substring(start + 1); - out.delete(start, out.length()); + String code = out.substring(start + 1, out.length() - 1); if (token && type == ENTITY_REF) { name = code; } - if (code.charAt(0) == '#') { - // TODO: check IndexOutOfBoundsException? - // TODO: save an intermediate string for 'code' if unneeded? - int c = code.charAt(1) == 'x' - ? Integer.parseInt(code.substring(2), 16) - : Integer.parseInt(code.substring(1)); - // TODO: set unresolved to false? - out.append((char) c); - return; - } - - String resolved = entityMap.get(code); - if (resolved != null) { - unresolved = false; + String resolved; + if (code.startsWith("#")) { + try { + int c = code.startsWith("#x") + ? Integer.parseInt(code.substring(2), 16) + : Integer.parseInt(code.substring(1)); + out.delete(start, out.length()); + out.appendCodePoint(c); + unresolved = false; + } catch (NumberFormatException notANumber) { + throw new XmlPullParserException("Invalid character reference: &" + code); + } catch (IllegalArgumentException invalidCodePoint) { + throw new XmlPullParserException("Invalid character reference: &" + code); + } + } else if ((resolved = entityMap.get(code)) != null) { + out.delete(start, out.length()); out.append(resolved); - return; - } - - unresolved = true; - if (!token) { - checkRelaxed("unresolved: &" + code + ";"); - // TODO: should the &code; show up in the text in relaxed mode? + unresolved = false; + } else { + // keep the unresolved entity "&code;" in the text for relaxed clients + unresolved = true; + if (!token) { + checkRelaxed("unresolved: &" + code + ";"); + } } } |