private static boolean parse(XMLTokener x, JSONObject context,
String name) throws JSONException {
char c;
int i;
String n;
JSONObject o = null;
String s;
Object t;
// Test for and skip past these forms:
// <!-- ... -->
// <! ... >
// <![ ... ]]>
// <? ... ?>
// Report errors for these forms:
// <>
// <=
// <<
t = x.nextToken();
// <!
if (t == BANG) {
c = x.next();
if (c == '-') {
if (x.next() == '-') {
x.skipPast("-->");
return false;
}
x.back();
} else if (c == '[') {
t = x.nextToken();
if (t.equals("CDATA")) {
if (x.next() == '[') {
s = x.nextCDATA();
if (s.length() > 0) {
context.accumulate("content", s);
}
return false;
}
}
throw x.syntaxError("Expected 'CDATA['");
}
i = 1;
do {
t = x.nextMeta();
if (t == null) {
throw x.syntaxError("Missing '>' after '<!'.");
} else if (t == LT) {
i += 1;
} else if (t == GT) {
i -= 1;
}
} while (i > 0);
return false;
} else if (t == QUEST) {
// <?
x.skipPast("?>");
return false;
} else if (t == SLASH) {
// Close tag </
if (name == null || !x.nextToken().equals(name)) {
throw x.syntaxError("Mismatched close tag");
}
if (x.nextToken() != GT) {
throw x.syntaxError("Misshaped close tag");
}
return true;
} else if (t instanceof Character) {
throw x.syntaxError("Misshaped tag");
// Open tag <
} else {
n = (String)t;
t = null;
o = new JSONObject();
for (;;) {
if (t == null) {
t = x.nextToken();
}
// attribute = value
if (t instanceof String) {
s = (String)t;
t = x.nextToken();
if (t == EQ) {
t = x.nextToken();
if (!(t instanceof String)) {
throw x.syntaxError("Missing value");
}
o.accumulate(s, t);
t = null;
} else {
o.accumulate(s, "");
}
// Empty tag <.../>
} else if (t == SLASH) {
if (x.nextToken() != GT) {
throw x.syntaxError("Misshaped tag");
}
context.accumulate(n, o);
return false;
// Content, between <...> and </...>
} else if (t == GT) {
for (;;) {
t = x.nextContent();
if (t == null) {
if (name != null) {
throw x.syntaxError("Unclosed tag " + name);
}
return false;
} else if (t instanceof String) {
s = (String)t;
if (s.length() > 0) {
o.accumulate("content", s);
}
// Nested element
} else if (t == LT) {
if (parse(x, o, n)) {
if (o.length() == 0) {
context.accumulate(n, "");
} else if (o.length() == 1 &&
o.opt("content") != null) {
context.accumulate(n, o.opt("content"));
} else {
context.accumulate(n, o);
}
return false;
}