summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--luni/src/test/java/org/apache/harmony/xml/PullParserTest.java50
-rw-r--r--xml/src/main/java/org/kxml2/io/KXmlParser.java58
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>&#65;</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 + ";");
+ }
}
}