* @version 2016-08-10
*/
@SuppressWarnings("boxing")
-public class XML {
- /** The Character '&'. */
- public static final Character AMP = '&';
-
- /** The Character '''. */
- public static final Character APOS = '\'';
-
- /** The Character '!'. */
- public static final Character BANG = '!';
-
- /** The Character '='. */
- public static final Character EQ = '=';
-
- /** The Character '>'. */
- public static final Character GT = '>';
-
- /** The Character '<'. */
- public static final Character LT = '<';
-
- /** The Character '?'. */
- public static final Character QUEST = '?';
-
- /** The Character '"'. */
- public static final Character QUOT = '"';
-
- /** The Character '/'. */
- public static final Character SLASH = '/';
-
- /**
- * Creates an iterator for navigating Code Points in a string instead of
- * characters. Once Java7 support is dropped, this can be replaced with
- * <code>
- * string.codePoints()
- * </code>
- * which is available in Java8 and above.
- *
- * @see <a href=
- * "http://stackoverflow.com/a/21791059/6030888">http://stackoverflow.com/a/21791059/6030888</a>
- */
- private static Iterable<Integer> codePointIterator(final String string) {
- return new Iterable<Integer>() {
- @Override
- public Iterator<Integer> iterator() {
- return new Iterator<Integer>() {
- private int nextIndex = 0;
- private int length = string.length();
-
- @Override
- public boolean hasNext() {
- return this.nextIndex < this.length;
- }
-
- @Override
- public Integer next() {
- int result = string.codePointAt(this.nextIndex);
- this.nextIndex += Character.charCount(result);
- return result;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
+public class XML
+{
+ /** The Character '&'. */
+ public static final Character AMP = '&';
+
+ /** The Character '''. */
+ public static final Character APOS = '\'';
+
+ /** The Character '!'. */
+ public static final Character BANG = '!';
+
+ /** The Character '='. */
+ public static final Character EQ = '=';
+
+ /** The Character '>'. */
+ public static final Character GT = '>';
+
+ /** The Character '<'. */
+ public static final Character LT = '<';
+
+ /** The Character '?'. */
+ public static final Character QUEST = '?';
+
+ /** The Character '"'. */
+ public static final Character QUOT = '"';
+
+ /** The Character '/'. */
+ public static final Character SLASH = '/';
+
+ /**
+ * Creates an iterator for navigating Code Points in a string instead of
+ * characters. Once Java7 support is dropped, this can be replaced with <code>
+ * string.codePoints()
+ * </code> which is available in Java8 and above.
+ *
+ * @see <a href=
+ * "http://stackoverflow.com/a/21791059/6030888">http://stackoverflow.com/a/21791059/6030888</a>
+ */
+ private static Iterable<Integer> codePointIterator(final String string)
+ {
+ return new Iterable<Integer>()
+ {
+ @Override
+ public Iterator<Integer> iterator()
+ {
+ return new Iterator<Integer>()
+ {
+ private int nextIndex = 0;
+
+ private int length = string.length();
+
+ @Override
+ public boolean hasNext()
+ {
+ return this.nextIndex < this.length;
+ }
+
+ @Override
+ public Integer next()
+ {
+ int result = string.codePointAt(this.nextIndex);
+ this.nextIndex += Character.charCount(result);
+ return result;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
};
+ }
+ };
+ }
+
+ /**
+ * Replace special characters with XML escapes:
+ *
+ * <pre>
+ * & <small>(ampersand)</small> is replaced by &amp;
+ * < <small>(less than)</small> is replaced by &lt;
+ * > <small>(greater than)</small> is replaced by &gt;
+ * " <small>(double quote)</small> is replaced by &quot;
+ * ' <small>(single quote / apostrophe)</small> is replaced by &apos;
+ * </pre>
+ *
+ * @param string
+ * The string to be escaped.
+ * @return The escaped string.
+ */
+ public static String escape(String string)
+ {
+ StringBuilder sb = new StringBuilder(string.length());
+ for (final int cp : codePointIterator(string))
+ {
+ switch (cp)
+ {
+ case '&':
+ sb.append("&");
+ break;
+ case '<':
+ sb.append("<");
+ break;
+ case '>':
+ sb.append(">");
+ break;
+ case '"':
+ sb.append(""");
+ break;
+ case '\'':
+ sb.append("'");
+ break;
+ default:
+ if (mustEscape(cp))
+ {
+ sb.append("&#x");
+ sb.append(Integer.toHexString(cp));
+ sb.append(';');
+ }
+ else
+ {
+ sb.appendCodePoint(cp);
+ }
+ }
}
-
- /**
- * Replace special characters with XML escapes:
+ return sb.toString();
+ }
+
+ /**
+ * @param cp
+ * code point to test
+ * @return true if the code point is not valid for an XML
+ */
+ private static boolean mustEscape(int cp)
+ {
+ /* Valid range from https://www.w3.org/TR/REC-xml/#charsets
*
- * <pre>
- * & <small>(ampersand)</small> is replaced by &amp;
- * < <small>(less than)</small> is replaced by &lt;
- * > <small>(greater than)</small> is replaced by &gt;
- * " <small>(double quote)</small> is replaced by &quot;
- * ' <small>(single quote / apostrophe)</small> is replaced by &apos;
- * </pre>
+ * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
*
- * @param string
- * The string to be escaped.
- * @return The escaped string.
+ * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
*/
- public static String escape(String string) {
- StringBuilder sb = new StringBuilder(string.length());
- for (final int cp : codePointIterator(string)) {
- switch (cp) {
- case '&':
- sb.append("&");
- break;
- case '<':
- sb.append("<");
- break;
- case '>':
- sb.append(">");
- break;
- case '"':
- sb.append(""");
- break;
- case '\'':
- sb.append("'");
- break;
- default:
- if (mustEscape(cp)) {
- sb.append("&#x");
- sb.append(Integer.toHexString(cp));
- sb.append(';');
- } else {
- sb.appendCodePoint(cp);
- }
- }
+ // isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <=
+ // 0x9F)
+ // all ISO control characters are out of range except tabs and new lines
+ return (Character.isISOControl(cp) && cp != 0x9 && cp != 0xA
+ && cp != 0xD) || !(
+ // valid the range of acceptable characters that aren't control
+ (cp >= 0x20 && cp <= 0xD7FF) || (cp >= 0xE000 && cp <= 0xFFFD)
+ || (cp >= 0x10000 && cp <= 0x10FFFF));
+ }
+
+ /**
+ * Removes XML escapes from the string.
+ *
+ * @param string
+ * string to remove escapes from
+ * @return string with converted entities
+ */
+ public static String unescape(String string)
+ {
+ StringBuilder sb = new StringBuilder(string.length());
+ for (int i = 0, length = string.length(); i < length; i++)
+ {
+ char c = string.charAt(i);
+ if (c == '&')
+ {
+ final int semic = string.indexOf(';', i);
+ if (semic > i)
+ {
+ final String entity = string.substring(i + 1, semic);
+ sb.append(XMLTokener.unescapeEntity(entity));
+ // skip past the entity we just parsed.
+ i += entity.length() + 1;
}
- return sb.toString();
+ else
+ {
+ // this shouldn't happen in most cases since the parser
+ // errors on unclosed entries.
+ sb.append(c);
+ }
+ }
+ else
+ {
+ // not part of an entity
+ sb.append(c);
+ }
}
-
- /**
- * @param cp code point to test
- * @return true if the code point is not valid for an XML
- */
- private static boolean mustEscape(int cp) {
- /* Valid range from https://www.w3.org/TR/REC-xml/#charsets
- *
- * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
- *
- * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
- */
- // isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <= 0x9F)
- // all ISO control characters are out of range except tabs and new lines
- return (Character.isISOControl(cp)
- && cp != 0x9
- && cp != 0xA
- && cp != 0xD
- ) || !(
- // valid the range of acceptable characters that aren't control
- (cp >= 0x20 && cp <= 0xD7FF)
- || (cp >= 0xE000 && cp <= 0xFFFD)
- || (cp >= 0x10000 && cp <= 0x10FFFF)
- )
- ;
+ return sb.toString();
+ }
+
+ /**
+ * Throw an exception if the string contains whitespace. Whitespace is not
+ * allowed in tagNames and attributes.
+ *
+ * @param string
+ * A string.
+ * @throws JSONException
+ * Thrown if the string contains whitespace or is empty.
+ */
+ public static void noSpace(String string) throws JSONException
+ {
+ int i, length = string.length();
+ if (length == 0)
+ {
+ throw new JSONException("Empty string.");
}
-
- /**
- * Removes XML escapes from the string.
- *
- * @param string
- * string to remove escapes from
- * @return string with converted entities
- */
- public static String unescape(String string) {
- StringBuilder sb = new StringBuilder(string.length());
- for (int i = 0, length = string.length(); i < length; i++) {
- char c = string.charAt(i);
- if (c == '&') {
- final int semic = string.indexOf(';', i);
- if (semic > i) {
- final String entity = string.substring(i + 1, semic);
- sb.append(XMLTokener.unescapeEntity(entity));
- // skip past the entity we just parsed.
- i += entity.length() + 1;
- } else {
- // this shouldn't happen in most cases since the parser
- // errors on unclosed entries.
- sb.append(c);
- }
- } else {
- // not part of an entity
- sb.append(c);
- }
- }
- return sb.toString();
+ for (i = 0; i < length; i += 1)
+ {
+ if (Character.isWhitespace(string.charAt(i)))
+ {
+ throw new JSONException(
+ "'" + string + "' contains a space character.");
+ }
}
-
- /**
- * Throw an exception if the string contains whitespace. Whitespace is not
- * allowed in tagNames and attributes.
- *
- * @param string
- * A string.
- * @throws JSONException Thrown if the string contains whitespace or is empty.
- */
- public static void noSpace(String string) throws JSONException {
- int i, length = string.length();
- if (length == 0) {
- throw new JSONException("Empty string.");
+ }
+
+ /**
+ * Scan the content following the named tag, attaching it to the context.
+ *
+ * @param x
+ * The XMLTokener containing the source string.
+ * @param context
+ * The JSONObject that will include the new material.
+ * @param name
+ * The tag name.
+ * @return true if the close tag is processed.
+ * @throws JSONException
+ */
+ private static boolean parse(XMLTokener x, JSONObject context,
+ String name, boolean keepStrings) throws JSONException
+ {
+ char c;
+ int i;
+ JSONObject jsonobject = null;
+ String string;
+ String tagName;
+ Object token;
+
+ // Test for and skip past these forms:
+ // <!-- ... -->
+ // <! ... >
+ // <![ ... ]]>
+ // <? ... ?>
+ // Report errors for these forms:
+ // <>
+ // <=
+ // <<
+
+ token = x.nextToken();
+
+ // <!
+
+ if (token == BANG)
+ {
+ c = x.next();
+ if (c == '-')
+ {
+ if (x.next() == '-')
+ {
+ x.skipPast("-->");
+ return false;
}
- for (i = 0; i < length; i += 1) {
- if (Character.isWhitespace(string.charAt(i))) {
- throw new JSONException("'" + string
- + "' contains a space character.");
+ x.back();
+ }
+ else if (c == '[')
+ {
+ token = x.nextToken();
+ if ("CDATA".equals(token))
+ {
+ if (x.next() == '[')
+ {
+ string = x.nextCDATA();
+ if (string.length() > 0)
+ {
+ context.accumulate("content", string);
}
+ return false;
+ }
+ }
+ throw x.syntaxError("Expected 'CDATA['");
+ }
+ i = 1;
+ do
+ {
+ token = x.nextMeta();
+ if (token == null)
+ {
+ throw x.syntaxError("Missing '>' after '<!'.");
+ }
+ else if (token == LT)
+ {
+ i += 1;
}
+ else if (token == GT)
+ {
+ i -= 1;
+ }
+ } while (i > 0);
+ return false;
}
+ else if (token == QUEST)
+ {
- /**
- * Scan the content following the named tag, attaching it to the context.
- *
- * @param x
- * The XMLTokener containing the source string.
- * @param context
- * The JSONObject that will include the new material.
- * @param name
- * The tag name.
- * @return true if the close tag is processed.
- * @throws JSONException
- */
- private static boolean parse(XMLTokener x, JSONObject context, String name, boolean keepStrings)
- throws JSONException {
- char c;
- int i;
- JSONObject jsonobject = null;
- String string;
- String tagName;
- Object token;
-
- // Test for and skip past these forms:
- // <!-- ... -->
- // <! ... >
- // <![ ... ]]>
- // <? ... ?>
- // Report errors for these forms:
- // <>
- // <=
- // <<
-
- token = x.nextToken();
-
- // <!
-
- if (token == BANG) {
- c = x.next();
- if (c == '-') {
- if (x.next() == '-') {
- x.skipPast("-->");
- return false;
- }
- x.back();
- } else if (c == '[') {
- token = x.nextToken();
- if ("CDATA".equals(token)) {
- if (x.next() == '[') {
- string = x.nextCDATA();
- if (string.length() > 0) {
- context.accumulate("content", string);
- }
- return false;
- }
- }
- throw x.syntaxError("Expected 'CDATA['");
- }
- i = 1;
- do {
- token = x.nextMeta();
- if (token == null) {
- throw x.syntaxError("Missing '>' after '<!'.");
- } else if (token == LT) {
- i += 1;
- } else if (token == GT) {
- i -= 1;
- }
- } while (i > 0);
- return false;
- } else if (token == QUEST) {
+ // <?
+ x.skipPast("?>");
+ return false;
+ }
+ else if (token == SLASH)
+ {
+
+ // Close tag </
+
+ token = x.nextToken();
+ if (name == null)
+ {
+ throw x.syntaxError("Mismatched close tag " + token);
+ }
+ if (!token.equals(name))
+ {
+ throw x.syntaxError("Mismatched " + name + " and " + token);
+ }
+ if (x.nextToken() != GT)
+ {
+ throw x.syntaxError("Misshaped close tag");
+ }
+ return true;
- // <?
- x.skipPast("?>");
- return false;
- } else if (token == SLASH) {
+ }
+ else if (token instanceof Character)
+ {
+ throw x.syntaxError("Misshaped tag");
- // Close tag </
+ // Open tag <
+ }
+ else
+ {
+ tagName = (String) token;
+ token = null;
+ jsonobject = new JSONObject();
+ for (;;)
+ {
+ if (token == null)
+ {
+ token = x.nextToken();
+ }
+ // attribute = value
+ if (token instanceof String)
+ {
+ string = (String) token;
+ token = x.nextToken();
+ if (token == EQ)
+ {
token = x.nextToken();
- if (name == null) {
- throw x.syntaxError("Mismatched close tag " + token);
- }
- if (!token.equals(name)) {
- throw x.syntaxError("Mismatched " + name + " and " + token);
- }
- if (x.nextToken() != GT) {
- throw x.syntaxError("Misshaped close tag");
+ if (!(token instanceof String))
+ {
+ throw x.syntaxError("Missing value");
}
- return true;
+ jsonobject.accumulate(string, keepStrings ? ((String) token)
+ : stringToValue((String) token));
+ token = null;
+ }
+ else
+ {
+ jsonobject.accumulate(string, "");
+ }
- } else if (token instanceof Character) {
+ }
+ else if (token == SLASH)
+ {
+ // Empty tag <.../>
+ if (x.nextToken() != GT)
+ {
throw x.syntaxError("Misshaped tag");
+ }
+ if (jsonobject.length() > 0)
+ {
+ context.accumulate(tagName, jsonobject);
+ }
+ else
+ {
+ context.accumulate(tagName, "");
+ }
+ return false;
- // Open tag <
+ }
+ else if (token == GT)
+ {
+ // Content, between <...> and </...>
+ for (;;)
+ {
+ token = x.nextContent();
+ if (token == null)
+ {
+ if (tagName != null)
+ {
+ throw x.syntaxError("Unclosed tag " + tagName);
+ }
+ return false;
+ }
+ else if (token instanceof String)
+ {
+ string = (String) token;
+ if (string.length() > 0)
+ {
+ jsonobject.accumulate("content",
+ keepStrings ? string : stringToValue(string));
+ }
- } else {
- tagName = (String) token;
- token = null;
- jsonobject = new JSONObject();
- for (;;) {
- if (token == null) {
- token = x.nextToken();
+ }
+ else if (token == LT)
+ {
+ // Nested element
+ if (parse(x, jsonobject, tagName, keepStrings))
+ {
+ if (jsonobject.length() == 0)
+ {
+ context.accumulate(tagName, "");
}
- // attribute = value
- if (token instanceof String) {
- string = (String) token;
- token = x.nextToken();
- if (token == EQ) {
- token = x.nextToken();
- if (!(token instanceof String)) {
- throw x.syntaxError("Missing value");
- }
- jsonobject.accumulate(string,
- keepStrings ? ((String)token) : stringToValue((String) token));
- token = null;
- } else {
- jsonobject.accumulate(string, "");
- }
-
-
- } else if (token == SLASH) {
- // Empty tag <.../>
- if (x.nextToken() != GT) {
- throw x.syntaxError("Misshaped tag");
- }
- if (jsonobject.length() > 0) {
- context.accumulate(tagName, jsonobject);
- } else {
- context.accumulate(tagName, "");
- }
- return false;
-
- } else if (token == GT) {
- // Content, between <...> and </...>
- for (;;) {
- token = x.nextContent();
- if (token == null) {
- if (tagName != null) {
- throw x.syntaxError("Unclosed tag " + tagName);
- }
- return false;
- } else if (token instanceof String) {
- string = (String) token;
- if (string.length() > 0) {
- jsonobject.accumulate("content",
- keepStrings ? string : stringToValue(string));
- }
-
- } else if (token == LT) {
- // Nested element
- if (parse(x, jsonobject, tagName,keepStrings)) {
- if (jsonobject.length() == 0) {
- context.accumulate(tagName, "");
- } else if (jsonobject.length() == 1
- && jsonobject.opt("content") != null) {
- context.accumulate(tagName,
- jsonobject.opt("content"));
- } else {
- context.accumulate(tagName, jsonobject);
- }
- return false;
- }
- }
- }
- } else {
- throw x.syntaxError("Misshaped tag");
+ else if (jsonobject.length() == 1
+ && jsonobject.opt("content") != null)
+ {
+ context.accumulate(tagName, jsonobject.opt("content"));
}
- }
- }
- }
-
- /**
- * This method is the same as {@link JSONObject#stringToValue(String)}.
- *
- * @param string String to convert
- * @return JSON value of this string or the string
- */
- // To maintain compatibility with the Android API, this method is a direct copy of
- // the one in JSONObject. Changes made here should be reflected there.
- public static Object stringToValue(String string) {
- if (string.equals("")) {
- return string;
- }
- if (string.equalsIgnoreCase("true")) {
- return Boolean.TRUE;
- }
- if (string.equalsIgnoreCase("false")) {
- return Boolean.FALSE;
- }
- if (string.equalsIgnoreCase("null")) {
- return JSONObject.NULL;
- }
-
- /*
- * If it might be a number, try converting it. If a number cannot be
- * produced, then the value will just be a string.
- */
-
- char initial = string.charAt(0);
- if ((initial >= '0' && initial <= '9') || initial == '-') {
- try {
- // if we want full Big Number support this block can be replaced with:
- // return stringToNumber(string);
- if (string.indexOf('.') > -1 || string.indexOf('e') > -1
- || string.indexOf('E') > -1 || "-0".equals(string)) {
- Double d = Double.valueOf(string);
- if (!d.isInfinite() && !d.isNaN()) {
- return d;
- }
- } else {
- Long myLong = Long.valueOf(string);
- if (string.equals(myLong.toString())) {
- if (myLong.longValue() == myLong.intValue()) {
- return Integer.valueOf(myLong.intValue());
- }
- return myLong;
- }
+ else
+ {
+ context.accumulate(tagName, jsonobject);
}
- } catch (Exception ignore) {
+ return false;
+ }
}
+ }
}
- return string;
+ else
+ {
+ throw x.syntaxError("Misshaped tag");
+ }
+ }
}
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * name/value pairs and arrays of values. JSON does not does not like to
- * distinguish between elements and attributes. Sequences of similar
- * elements are represented as JSONArrays. Content text may be placed in a
- * "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
- * are ignored.
- *
- * @param string
- * The source string.
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(String string) throws JSONException {
- return toJSONObject(string, false);
+ }
+
+ /**
+ * This method is the same as {@link JSONObject#stringToValue(String)}.
+ *
+ * @param string
+ * String to convert
+ * @return JSON value of this string or the string
+ */
+ // To maintain compatibility with the Android API, this method is a direct
+ // copy of
+ // the one in JSONObject. Changes made here should be reflected there.
+ public static Object stringToValue(String string)
+ {
+ if (string.equals(""))
+ {
+ return string;
}
-
- /**
- * Convert a well-formed (but not necessarily valid) XML into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * name/value pairs and arrays of values. JSON does not does not like to
- * distinguish between elements and attributes. Sequences of similar
- * elements are represented as JSONArrays. Content text may be placed in a
- * "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
- * are ignored.
- *
- * @param reader The XML source reader.
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(Reader reader) throws JSONException {
- return toJSONObject(reader, false);
+ if (string.equalsIgnoreCase("true"))
+ {
+ return Boolean.TRUE;
+ }
+ if (string.equalsIgnoreCase("false"))
+ {
+ return Boolean.FALSE;
+ }
+ if (string.equalsIgnoreCase("null"))
+ {
+ return JSONObject.NULL;
}
- /**
- * Convert a well-formed (but not necessarily valid) XML into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * name/value pairs and arrays of values. JSON does not does not like to
- * distinguish between elements and attributes. Sequences of similar
- * elements are represented as JSONArrays. Content text may be placed in a
- * "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
- * are ignored.
- *
- * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
- * numbers but will instead be the exact value as seen in the XML document.
- *
- * @param reader The XML source reader.
- * @param keepStrings If true, then values will not be coerced into boolean
- * or numeric values and will instead be left as strings
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
+ /*
+ * If it might be a number, try converting it. If a number cannot be
+ * produced, then the value will just be a string.
*/
- public static JSONObject toJSONObject(Reader reader, boolean keepStrings) throws JSONException {
- JSONObject jo = new JSONObject();
- XMLTokener x = new XMLTokener(reader);
- while (x.more()) {
- x.skipPast("<");
- if(x.more()) {
- parse(x, jo, null, keepStrings);
+
+ char initial = string.charAt(0);
+ if ((initial >= '0' && initial <= '9') || initial == '-')
+ {
+ try
+ {
+ // if we want full Big Number support this block can be replaced with:
+ // return stringToNumber(string);
+ if (string.indexOf('.') > -1 || string.indexOf('e') > -1
+ || string.indexOf('E') > -1 || "-0".equals(string))
+ {
+ Double d = Double.valueOf(string);
+ if (!d.isInfinite() && !d.isNaN())
+ {
+ return d;
+ }
+ }
+ else
+ {
+ Long myLong = Long.valueOf(string);
+ if (string.equals(myLong.toString()))
+ {
+ if (myLong.longValue() == myLong.intValue())
+ {
+ return Integer.valueOf(myLong.intValue());
}
+ return myLong;
+ }
}
- return jo;
- }
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * name/value pairs and arrays of values. JSON does not does not like to
- * distinguish between elements and attributes. Sequences of similar
- * elements are represented as JSONArrays. Content text may be placed in a
- * "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
- * are ignored.
- *
- * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
- * numbers but will instead be the exact value as seen in the XML document.
- *
- * @param string
- * The source string.
- * @param keepStrings If true, then values will not be coerced into boolean
- * or numeric values and will instead be left as strings
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
- return toJSONObject(new StringReader(string), keepStrings);
+ } catch (Exception ignore)
+ {
+ }
}
-
- /**
- * Convert a JSONObject into a well-formed, element-normal XML string.
- *
- * @param object
- * A JSONObject.
- * @return A string.
- * @throws JSONException Thrown if there is an error parsing the string
- */
- public static String toString(Object object) throws JSONException {
- return toString(object, null);
+ return string;
+ }
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONObject. Some information may be lost in this transformation because
+ * JSON is a data format and XML is a document format. XML uses elements,
+ * attributes, and content text, while JSON uses unordered collections of
+ * name/value pairs and arrays of values. JSON does not does not like to
+ * distinguish between elements and attributes. Sequences of similar elements
+ * are represented as JSONArrays. Content text may be placed in a "content"
+ * member. Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
+ *
+ * @param string
+ * The source string.
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException
+ * Thrown if there is an errors while parsing the string
+ */
+ public static JSONObject toJSONObject(String string) throws JSONException
+ {
+ return toJSONObject(string, false);
+ }
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML into a JSONObject.
+ * Some information may be lost in this transformation because JSON is a data
+ * format and XML is a document format. XML uses elements, attributes, and
+ * content text, while JSON uses unordered collections of name/value pairs and
+ * arrays of values. JSON does not does not like to distinguish between
+ * elements and attributes. Sequences of similar elements are represented as
+ * JSONArrays. Content text may be placed in a "content" member. Comments,
+ * prologs, DTDs, and <code><[ [ ]]></code> are ignored.
+ *
+ * @param reader
+ * The XML source reader.
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException
+ * Thrown if there is an errors while parsing the string
+ */
+ public static JSONObject toJSONObject(Reader reader) throws JSONException
+ {
+ return toJSONObject(reader, false);
+ }
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML into a JSONObject.
+ * Some information may be lost in this transformation because JSON is a data
+ * format and XML is a document format. XML uses elements, attributes, and
+ * content text, while JSON uses unordered collections of name/value pairs and
+ * arrays of values. JSON does not does not like to distinguish between
+ * elements and attributes. Sequences of similar elements are represented as
+ * JSONArrays. Content text may be placed in a "content" member. Comments,
+ * prologs, DTDs, and <code><[ [ ]]></code> are ignored.
+ *
+ * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
+ * numbers but will instead be the exact value as seen in the XML document.
+ *
+ * @param reader
+ * The XML source reader.
+ * @param keepStrings
+ * If true, then values will not be coerced into boolean or numeric
+ * values and will instead be left as strings
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException
+ * Thrown if there is an errors while parsing the string
+ */
+ public static JSONObject toJSONObject(Reader reader, boolean keepStrings)
+ throws JSONException
+ {
+ JSONObject jo = new JSONObject();
+ XMLTokener x = new XMLTokener(reader);
+ while (x.more())
+ {
+ x.skipPast("<");
+ if (x.more())
+ {
+ parse(x, jo, null, keepStrings);
+ }
}
+ return jo;
+ }
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONObject. Some information may be lost in this transformation because
+ * JSON is a data format and XML is a document format. XML uses elements,
+ * attributes, and content text, while JSON uses unordered collections of
+ * name/value pairs and arrays of values. JSON does not does not like to
+ * distinguish between elements and attributes. Sequences of similar elements
+ * are represented as JSONArrays. Content text may be placed in a "content"
+ * member. Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
+ *
+ * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
+ * numbers but will instead be the exact value as seen in the XML document.
+ *
+ * @param string
+ * The source string.
+ * @param keepStrings
+ * If true, then values will not be coerced into boolean or numeric
+ * values and will instead be left as strings
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException
+ * Thrown if there is an errors while parsing the string
+ */
+ public static JSONObject toJSONObject(String string, boolean keepStrings)
+ throws JSONException
+ {
+ return toJSONObject(new StringReader(string), keepStrings);
+ }
+
+ /**
+ * Convert a JSONObject into a well-formed, element-normal XML string.
+ *
+ * @param object
+ * A JSONObject.
+ * @return A string.
+ * @throws JSONException
+ * Thrown if there is an error parsing the string
+ */
+ public static String toString(Object object) throws JSONException
+ {
+ return toString(object, null);
+ }
+
+ /**
+ * Convert a JSONObject into a well-formed, element-normal XML string.
+ *
+ * @param object
+ * A JSONObject.
+ * @param tagName
+ * The optional name of the enclosing tag.
+ * @return A string.
+ * @throws JSONException
+ * Thrown if there is an error parsing the string
+ */
+ public static String toString(final Object object, final String tagName)
+ throws JSONException
+ {
+ StringBuilder sb = new StringBuilder();
+ JSONArray ja;
+ JSONObject jo;
+ String string;
+
+ if (object instanceof JSONObject)
+ {
+
+ // Emit <tagName>
+ if (tagName != null)
+ {
+ sb.append('<');
+ sb.append(tagName);
+ sb.append('>');
+ }
+
+ // Loop thru the keys.
+ // don't use the new entrySet accessor to maintain Android Support
+ jo = (JSONObject) object;
+ for (final String key : jo.keySet())
+ {
+ Object value = jo.opt(key);
+ if (value == null)
+ {
+ value = "";
+ }
+ else if (value.getClass().isArray())
+ {
+ value = new JSONArray(value);
+ }
- /**
- * Convert a JSONObject into a well-formed, element-normal XML string.
- *
- * @param object
- * A JSONObject.
- * @param tagName
- * The optional name of the enclosing tag.
- * @return A string.
- * @throws JSONException Thrown if there is an error parsing the string
- */
- public static String toString(final Object object, final String tagName)
- throws JSONException {
- StringBuilder sb = new StringBuilder();
- JSONArray ja;
- JSONObject jo;
- String string;
-
- if (object instanceof JSONObject) {
-
- // Emit <tagName>
- if (tagName != null) {
- sb.append('<');
- sb.append(tagName);
- sb.append('>');
+ // Emit content in body
+ if ("content".equals(key))
+ {
+ if (value instanceof JSONArray)
+ {
+ ja = (JSONArray) value;
+ int jaLength = ja.length();
+ // don't use the new iterator API to maintain support for Android
+ for (int i = 0; i < jaLength; i++)
+ {
+ if (i > 0)
+ {
+ sb.append('\n');
+ }
+ Object val = ja.opt(i);
+ sb.append(escape(val.toString()));
}
+ }
+ else
+ {
+ sb.append(escape(value.toString()));
+ }
- // Loop thru the keys.
- // don't use the new entrySet accessor to maintain Android Support
- jo = (JSONObject) object;
- for (final String key : jo.keySet()) {
- Object value = jo.opt(key);
- if (value == null) {
- value = "";
- } else if (value.getClass().isArray()) {
- value = new JSONArray(value);
- }
+ // Emit an array of similar keys
- // Emit content in body
- if ("content".equals(key)) {
- if (value instanceof JSONArray) {
- ja = (JSONArray) value;
- int jaLength = ja.length();
- // don't use the new iterator API to maintain support for Android
- for (int i = 0; i < jaLength; i++) {
- if (i > 0) {
- sb.append('\n');
- }
- Object val = ja.opt(i);
- sb.append(escape(val.toString()));
- }
- } else {
- sb.append(escape(value.toString()));
- }
-
- // Emit an array of similar keys
-
- } else if (value instanceof JSONArray) {
- ja = (JSONArray) value;
- int jaLength = ja.length();
- // don't use the new iterator API to maintain support for Android
- for (int i = 0; i < jaLength; i++) {
- Object val = ja.opt(i);
- if (val instanceof JSONArray) {
- sb.append('<');
- sb.append(key);
- sb.append('>');
- sb.append(toString(val));
- sb.append("</");
- sb.append(key);
- sb.append('>');
- } else {
- sb.append(toString(val, key));
- }
- }
- } else if ("".equals(value)) {
- sb.append('<');
- sb.append(key);
- sb.append("/>");
-
- // Emit a new tag <k>
-
- } else {
- sb.append(toString(value, key));
- }
+ }
+ else if (value instanceof JSONArray)
+ {
+ ja = (JSONArray) value;
+ int jaLength = ja.length();
+ // don't use the new iterator API to maintain support for Android
+ for (int i = 0; i < jaLength; i++)
+ {
+ Object val = ja.opt(i);
+ if (val instanceof JSONArray)
+ {
+ sb.append('<');
+ sb.append(key);
+ sb.append('>');
+ sb.append(toString(val));
+ sb.append("</");
+ sb.append(key);
+ sb.append('>');
}
- if (tagName != null) {
-
- // Emit the </tagname> close tag
- sb.append("</");
- sb.append(tagName);
- sb.append('>');
+ else
+ {
+ sb.append(toString(val, key));
}
- return sb.toString();
-
+ }
}
+ else if ("".equals(value))
+ {
+ sb.append('<');
+ sb.append(key);
+ sb.append("/>");
- if (object != null && (object instanceof JSONArray || object.getClass().isArray())) {
- if(object.getClass().isArray()) {
- ja = new JSONArray(object);
- } else {
- ja = (JSONArray) object;
- }
- int jaLength = ja.length();
- // don't use the new iterator API to maintain support for Android
- for (int i = 0; i < jaLength; i++) {
- Object val = ja.opt(i);
- // XML does not have good support for arrays. If an array
- // appears in a place where XML is lacking, synthesize an
- // <array> element.
- sb.append(toString(val, tagName == null ? "array" : tagName));
- }
- return sb.toString();
+ // Emit a new tag <k>
+
+ }
+ else
+ {
+ sb.append(toString(value, key));
}
+ }
+ if (tagName != null)
+ {
+
+ // Emit the </tagname> close tag
+ sb.append("</");
+ sb.append(tagName);
+ sb.append('>');
+ }
+ return sb.toString();
- string = (object == null) ? "null" : escape(object.toString());
- return (tagName == null) ? "\"" + string + "\""
- : (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName
- + ">" + string + "</" + tagName + ">";
+ }
+ if (object != null
+ && (object instanceof JSONArray || object.getClass().isArray()))
+ {
+ if (object.getClass().isArray())
+ {
+ ja = new JSONArray(object);
+ }
+ else
+ {
+ ja = (JSONArray) object;
+ }
+ int jaLength = ja.length();
+ // don't use the new iterator API to maintain support for Android
+ for (int i = 0; i < jaLength; i++)
+ {
+ Object val = ja.opt(i);
+ // XML does not have good support for arrays. If an array
+ // appears in a place where XML is lacking, synthesize an
+ // <array> element.
+ sb.append(toString(val, tagName == null ? "array" : tagName));
+ }
+ return sb.toString();
}
+
+ string = (object == null) ? "null" : escape(object.toString());
+ return (tagName == null) ? "\"" + string + "\""
+ : (string.length() == 0) ? "<" + tagName + "/>"
+ : "<" + tagName + ">" + string + "</" + tagName + ">";
+
+ }
}