You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2012/05/18 13:39:32 UTC
[3/7] Update JSON2 classes
http://git-wip-us.apache.org/repos/asf/wicket/blob/0c01d793/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONML.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONML.java b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONML.java
index f58f8e4..3fcdcea 100755
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONML.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONML.java
@@ -1,576 +1,465 @@
package org.apache.wicket.ajax.json;
/*
- Copyright (c) 2008 JSON.org
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- The Software shall be used for Good, not Evil.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
+Copyright (c) 2008 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
import java.util.Iterator;
/**
- * This provides static methods to convert an XML text into a JSONArray or JSONObject, and to covert
- * a JSONArray or JSONObject into an XML text using the JsonML transform.
- *
+ * This provides static methods to convert an XML text into a JSONArray or
+ * JSONObject, and to covert a JSONArray or JSONObject into an XML text using
+ * the JsonML transform.
* @author JSON.org
- * @version 2011-10-05
+ * @version 2011-11-24
*/
-public class JSONML
-{
-
- /**
- * Parse XML values and store them in a JSONArray.
- *
- * @param x
- * The XMLTokener containing the source string.
- * @param arrayForm
- * true if array form, false if object form.
- * @param ja
- * The JSONArray that is containing the current tag or null if we are at the
- * outermost level.
- * @return A JSONArray if the value is the outermost tag, otherwise null.
- * @throws JSONException
- */
- private static Object parse(XMLTokener x, boolean arrayForm, JSONArray ja) throws JSONException
- {
- String attribute;
- char c;
- String closeTag = null;
- int i;
- JSONArray newja = null;
- JSONObject newjo = null;
- Object token;
- String tagName = null;
+public class JSONML {
+
+ /**
+ * Parse XML values and store them in a JSONArray.
+ * @param x The XMLTokener containing the source string.
+ * @param arrayForm true if array form, false if object form.
+ * @param ja The JSONArray that is containing the current tag or null
+ * if we are at the outermost level.
+ * @return A JSONArray if the value is the outermost tag, otherwise null.
+ * @throws JSONException
+ */
+ private static Object parse(
+ XMLTokener x,
+ boolean arrayForm,
+ JSONArray ja
+ ) throws JSONException {
+ String attribute;
+ char c;
+ String closeTag = null;
+ int i;
+ JSONArray newja = null;
+ JSONObject newjo = null;
+ Object token;
+ String tagName = null;
// Test for and skip past these forms:
-// <!-- ... -->
-// <![ ... ]]>
-// <! ... >
-// <? ... ?>
-
- while (true)
- {
- if (!x.more())
- {
- throw x.syntaxError("Bad XML");
- }
- token = x.nextContent();
- if (token == XML.LT)
- {
- token = x.nextToken();
- if (token instanceof Character)
- {
- if (token == XML.SLASH)
- {
+// <!-- ... -->
+// <![ ... ]]>
+// <! ... >
+// <? ... ?>
+
+ while (true) {
+ if (!x.more()) {
+ throw x.syntaxError("Bad XML");
+ }
+ token = x.nextContent();
+ if (token == XML.LT) {
+ token = x.nextToken();
+ if (token instanceof Character) {
+ if (token == XML.SLASH) {
// Close tag </
- token = x.nextToken();
- if (!(token instanceof String))
- {
- throw new JSONException("Expected a closing name instead of '" + token +
- "'.");
- }
- if (x.nextToken() != XML.GT)
- {
- throw x.syntaxError("Misshaped close tag");
- }
- return token;
- }
- else if (token == XML.BANG)
- {
+ token = x.nextToken();
+ if (!(token instanceof String)) {
+ throw new JSONException(
+ "Expected a closing name instead of '" +
+ token + "'.");
+ }
+ if (x.nextToken() != XML.GT) {
+ throw x.syntaxError("Misshaped close tag");
+ }
+ return token;
+ } else if (token == XML.BANG) {
// <!
- c = x.next();
- if (c == '-')
- {
- if (x.next() == '-')
- {
- x.skipPast("-->");
- }
- x.back();
- }
- else if (c == '[')
- {
- token = x.nextToken();
- if (token.equals("CDATA") && x.next() == '[')
- {
- if (ja != null)
- {
- ja.put(x.nextCDATA());
- }
- }
- else
- {
- throw x.syntaxError("Expected 'CDATA['");
- }
- }
- else
- {
- i = 1;
- do
- {
- token = x.nextMeta();
- if (token == null)
- {
- throw x.syntaxError("Missing '>' after '<!'.");
- }
- else if (token == XML.LT)
- {
- i += 1;
- }
- else if (token == XML.GT)
- {
- i -= 1;
- }
- }
- while (i > 0);
- }
- }
- else if (token == XML.QUEST)
- {
+ c = x.next();
+ if (c == '-') {
+ if (x.next() == '-') {
+ x.skipPast("-->");
+ }
+ x.back();
+ } else if (c == '[') {
+ token = x.nextToken();
+ if (token.equals("CDATA") && x.next() == '[') {
+ if (ja != null) {
+ ja.put(x.nextCDATA());
+ }
+ } else {
+ throw x.syntaxError("Expected 'CDATA['");
+ }
+ } else {
+ i = 1;
+ do {
+ token = x.nextMeta();
+ if (token == null) {
+ throw x.syntaxError("Missing '>' after '<!'.");
+ } else if (token == XML.LT) {
+ i += 1;
+ } else if (token == XML.GT) {
+ i -= 1;
+ }
+ } while (i > 0);
+ }
+ } else if (token == XML.QUEST) {
// <?
- x.skipPast("?>");
- }
- else
- {
- throw x.syntaxError("Misshaped tag");
- }
+ x.skipPast("?>");
+ } else {
+ throw x.syntaxError("Misshaped tag");
+ }
// Open tag <
- }
- else
- {
- if (!(token instanceof String))
- {
- throw x.syntaxError("Bad tagName '" + token + "'.");
- }
- tagName = (String)token;
- newja = new JSONArray();
- newjo = new JSONObject();
- if (arrayForm)
- {
- newja.put(tagName);
- if (ja != null)
- {
- ja.put(newja);
- }
- }
- else
- {
- newjo.put("tagName", tagName);
- if (ja != null)
- {
- ja.put(newjo);
- }
- }
- token = null;
- for (;;)
- {
- if (token == null)
- {
- token = x.nextToken();
- }
- if (token == null)
- {
- throw x.syntaxError("Misshaped tag");
- }
- if (!(token instanceof String))
- {
- break;
- }
+ } else {
+ if (!(token instanceof String)) {
+ throw x.syntaxError("Bad tagName '" + token + "'.");
+ }
+ tagName = (String)token;
+ newja = new JSONArray();
+ newjo = new JSONObject();
+ if (arrayForm) {
+ newja.put(tagName);
+ if (ja != null) {
+ ja.put(newja);
+ }
+ } else {
+ newjo.put("tagName", tagName);
+ if (ja != null) {
+ ja.put(newjo);
+ }
+ }
+ token = null;
+ for (;;) {
+ if (token == null) {
+ token = x.nextToken();
+ }
+ if (token == null) {
+ throw x.syntaxError("Misshaped tag");
+ }
+ if (!(token instanceof String)) {
+ break;
+ }
// attribute = value
- attribute = (String)token;
- if (!arrayForm && (attribute == "tagName" || attribute == "childNode"))
- {
- throw x.syntaxError("Reserved attribute.");
- }
- token = x.nextToken();
- if (token == XML.EQ)
- {
- token = x.nextToken();
- if (!(token instanceof String))
- {
- throw x.syntaxError("Missing value");
- }
- newjo.accumulate(attribute, XML.stringToValue((String)token));
- token = null;
- }
- else
- {
- newjo.accumulate(attribute, "");
- }
- }
- if (arrayForm && newjo.length() > 0)
- {
- newja.put(newjo);
- }
+ attribute = (String)token;
+ if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) {
+ throw x.syntaxError("Reserved attribute.");
+ }
+ token = x.nextToken();
+ if (token == XML.EQ) {
+ token = x.nextToken();
+ if (!(token instanceof String)) {
+ throw x.syntaxError("Missing value");
+ }
+ newjo.accumulate(attribute, XML.stringToValue((String)token));
+ token = null;
+ } else {
+ newjo.accumulate(attribute, "");
+ }
+ }
+ if (arrayForm && newjo.length() > 0) {
+ newja.put(newjo);
+ }
// Empty tag <.../>
- if (token == XML.SLASH)
- {
- if (x.nextToken() != XML.GT)
- {
- throw x.syntaxError("Misshaped tag");
- }
- if (ja == null)
- {
- if (arrayForm)
- {
- return newja;
- }
- else
- {
- return newjo;
- }
- }
+ if (token == XML.SLASH) {
+ if (x.nextToken() != XML.GT) {
+ throw x.syntaxError("Misshaped tag");
+ }
+ if (ja == null) {
+ if (arrayForm) {
+ return newja;
+ } else {
+ return newjo;
+ }
+ }
// Content, between <...> and </...>
- }
- else
- {
- if (token != XML.GT)
- {
- throw x.syntaxError("Misshaped tag");
- }
- closeTag = (String)parse(x, arrayForm, newja);
- if (closeTag != null)
- {
- if (!closeTag.equals(tagName))
- {
- throw x.syntaxError("Mismatched '" + tagName + "' and '" +
- closeTag + "'");
- }
- tagName = null;
- if (!arrayForm && newja.length() > 0)
- {
- newjo.put("childNodes", newja);
- }
- if (ja == null)
- {
- if (arrayForm)
- {
- return newja;
- }
- else
- {
- return newjo;
- }
- }
- }
- }
- }
- }
- else
- {
- if (ja != null)
- {
- ja.put(token instanceof String ? XML.stringToValue((String)token) : token);
- }
- }
- }
- }
-
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a JSONArray using the
- * JsonML transform. Each XML tag is represented as a JSONArray in which the first element is
- * the tag name. If the tag has attributes, then the second element will be JSONObject
- * containing the name/value pairs. If the tag contains children, then strings and JSONArrays
- * will represent the child tags. Comments, prologs, DTDs, and <code><[ [ ]]></code> are
- * ignored.
- *
- * @param string
- * The source string.
- * @return A JSONArray containing the structured data from the XML string.
- * @throws JSONException
- */
- public static JSONArray toJSONArray(String string) throws JSONException
- {
- return toJSONArray(new XMLTokener(string));
- }
-
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a JSONArray using the
- * JsonML transform. Each XML tag is represented as a JSONArray in which the first element is
- * the tag name. If the tag has attributes, then the second element will be JSONObject
- * containing the name/value pairs. If the tag contains children, then strings and JSONArrays
- * will represent the child content and tags. Comments, prologs, DTDs, and
- * <code><[ [ ]]></code> are ignored.
- *
- * @param x
- * An XMLTokener.
- * @return A JSONArray containing the structured data from the XML string.
- * @throws JSONException
- */
- public static JSONArray toJSONArray(XMLTokener x) throws JSONException
- {
- return (JSONArray)parse(x, true, null);
- }
-
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a JSONObject using the
- * JsonML transform. Each XML tag is represented as a JSONObject with a "tagName" property. If
- * the tag has attributes, then the attributes will be in the JSONObject as properties. If the
- * tag contains children, the object will have a "childNodes" property which will be an array of
- * strings and JsonML JSONObjects.
- *
- * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
- *
- * @param x
- * An XMLTokener of the XML source text.
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException
- */
- public static JSONObject toJSONObject(XMLTokener x) throws JSONException
- {
- return (JSONObject)parse(x, false, null);
- }
-
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a JSONObject using the
- * JsonML transform. Each XML tag is represented as a JSONObject with a "tagName" property. If
- * the tag has attributes, then the attributes will be in the JSONObject as properties. If the
- * tag contains children, the object will have a "childNodes" property which will be an array of
- * strings and JsonML JSONObjects.
- *
- * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
- *
- * @param string
- * The XML source text.
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException
- */
- public static JSONObject toJSONObject(String string) throws JSONException
- {
- return toJSONObject(new XMLTokener(string));
- }
-
-
- /**
- * Reverse the JSONML transformation, making an XML text from a JSONArray.
- *
- * @param ja
- * A JSONArray.
- * @return An XML string.
- * @throws JSONException
- */
- public static String toString(JSONArray ja) throws JSONException
- {
- int i;
- JSONObject jo;
- String key;
- Iterator keys;
- int length;
- Object object;
- StringBuffer sb = new StringBuffer();
- String tagName;
- String value;
+ } else {
+ if (token != XML.GT) {
+ throw x.syntaxError("Misshaped tag");
+ }
+ closeTag = (String)parse(x, arrayForm, newja);
+ if (closeTag != null) {
+ if (!closeTag.equals(tagName)) {
+ throw x.syntaxError("Mismatched '" + tagName +
+ "' and '" + closeTag + "'");
+ }
+ tagName = null;
+ if (!arrayForm && newja.length() > 0) {
+ newjo.put("childNodes", newja);
+ }
+ if (ja == null) {
+ if (arrayForm) {
+ return newja;
+ } else {
+ return newjo;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if (ja != null) {
+ ja.put(token instanceof String
+ ? XML.stringToValue((String)token)
+ : token);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONArray using the JsonML transform. Each XML tag is represented as
+ * a JSONArray in which the first element is the tag name. If the tag has
+ * attributes, then the second element will be JSONObject containing the
+ * name/value pairs. If the tag contains children, then strings and
+ * JSONArrays will represent the child tags.
+ * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
+ * @param string The source string.
+ * @return A JSONArray containing the structured data from the XML string.
+ * @throws JSONException
+ */
+ public static JSONArray toJSONArray(String string) throws JSONException {
+ return toJSONArray(new XMLTokener(string));
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONArray using the JsonML transform. Each XML tag is represented as
+ * a JSONArray in which the first element is the tag name. If the tag has
+ * attributes, then the second element will be JSONObject containing the
+ * name/value pairs. If the tag contains children, then strings and
+ * JSONArrays will represent the child content and tags.
+ * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
+ * @param x An XMLTokener.
+ * @return A JSONArray containing the structured data from the XML string.
+ * @throws JSONException
+ */
+ public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
+ return (JSONArray)parse(x, true, null);
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONObject using the JsonML transform. Each XML tag is represented as
+ * a JSONObject with a "tagName" property. If the tag has attributes, then
+ * the attributes will be in the JSONObject as properties. If the tag
+ * contains children, the object will have a "childNodes" property which
+ * will be an array of strings and JsonML JSONObjects.
+
+ * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
+ * @param x An XMLTokener of the XML source text.
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException
+ */
+ public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
+ return (JSONObject)parse(x, false, null);
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONObject using the JsonML transform. Each XML tag is represented as
+ * a JSONObject with a "tagName" property. If the tag has attributes, then
+ * the attributes will be in the JSONObject as properties. If the tag
+ * contains children, the object will have a "childNodes" property which
+ * will be an array of strings and JsonML JSONObjects.
+
+ * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
+ * @param string The XML source text.
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException
+ */
+ public static JSONObject toJSONObject(String string) throws JSONException {
+ return toJSONObject(new XMLTokener(string));
+ }
+
+
+ /**
+ * Reverse the JSONML transformation, making an XML text from a JSONArray.
+ * @param ja A JSONArray.
+ * @return An XML string.
+ * @throws JSONException
+ */
+ public static String toString(JSONArray ja) throws JSONException {
+ int i;
+ JSONObject jo;
+ String key;
+ Iterator keys;
+ int length;
+ Object object;
+ StringBuffer sb = new StringBuffer();
+ String tagName;
+ String value;
// Emit <tagName
- tagName = ja.getString(0);
- XML.noSpace(tagName);
- tagName = XML.escape(tagName);
- sb.append('<');
- sb.append(tagName);
-
- object = ja.opt(1);
- if (object instanceof JSONObject)
- {
- i = 2;
- jo = (JSONObject)object;
-
-// Emit the attributes
-
- keys = jo.keys();
- while (keys.hasNext())
- {
- key = keys.next().toString();
- XML.noSpace(key);
- value = jo.optString(key);
- if (value != null)
- {
- sb.append(' ');
- sb.append(XML.escape(key));
- sb.append('=');
- sb.append('"');
- sb.append(XML.escape(value));
- sb.append('"');
- }
- }
- }
- else
- {
- i = 1;
- }
-
-// Emit content in body
-
- length = ja.length();
- if (i >= length)
- {
- sb.append('/');
- sb.append('>');
- }
- else
- {
- sb.append('>');
- do
- {
- object = ja.get(i);
- i += 1;
- if (object != null)
- {
- if (object instanceof String)
- {
- sb.append(XML.escape(object.toString()));
- }
- else if (object instanceof JSONObject)
- {
- sb.append(toString((JSONObject)object));
- }
- else if (object instanceof JSONArray)
- {
- sb.append(toString((JSONArray)object));
- }
- }
- }
- while (i < length);
- sb.append('<');
- sb.append('/');
- sb.append(tagName);
- sb.append('>');
- }
- return sb.toString();
- }
-
- /**
- * Reverse the JSONML transformation, making an XML text from a JSONObject. The JSONObject must
- * contain a "tagName" property. If it has children, then it must have a "childNodes" property
- * containing an array of objects. The other properties are attributes with string values.
- *
- * @param jo
- * A JSONObject.
- * @return An XML string.
- * @throws JSONException
- */
- public static String toString(JSONObject jo) throws JSONException
- {
- StringBuffer sb = new StringBuffer();
- int i;
- JSONArray ja;
- String key;
- Iterator keys;
- int length;
- Object object;
- String tagName;
- String value;
-
-// Emit <tagName
+ tagName = ja.getString(0);
+ XML.noSpace(tagName);
+ tagName = XML.escape(tagName);
+ sb.append('<');
+ sb.append(tagName);
- tagName = jo.optString("tagName");
- if (tagName == null)
- {
- return XML.escape(jo.toString());
- }
- XML.noSpace(tagName);
- tagName = XML.escape(tagName);
- sb.append('<');
- sb.append(tagName);
+ object = ja.opt(1);
+ if (object instanceof JSONObject) {
+ i = 2;
+ jo = (JSONObject)object;
// Emit the attributes
- keys = jo.keys();
- while (keys.hasNext())
- {
- key = keys.next().toString();
- if (!key.equals("tagName") && !key.equals("childNodes"))
- {
- XML.noSpace(key);
- value = jo.optString(key);
- if (value != null)
- {
- sb.append(' ');
- sb.append(XML.escape(key));
- sb.append('=');
- sb.append('"');
- sb.append(XML.escape(value));
- sb.append('"');
- }
- }
- }
-
-// Emit content in body
-
- ja = jo.optJSONArray("childNodes");
- if (ja == null)
- {
- sb.append('/');
- sb.append('>');
- }
- else
- {
- sb.append('>');
- length = ja.length();
- for (i = 0; i < length; i += 1)
- {
- object = ja.get(i);
- if (object != null)
- {
- if (object instanceof String)
- {
- sb.append(XML.escape(object.toString()));
- }
- else if (object instanceof JSONObject)
- {
- sb.append(toString((JSONObject)object));
- }
- else if (object instanceof JSONArray)
- {
- sb.append(toString((JSONArray)object));
- }
- else
- {
- sb.append(object.toString());
- }
- }
- }
- sb.append('<');
- sb.append('/');
- sb.append(tagName);
- sb.append('>');
- }
- return sb.toString();
- }
-}
\ No newline at end of file
+ keys = jo.keys();
+ while (keys.hasNext()) {
+ key = keys.next().toString();
+ XML.noSpace(key);
+ value = jo.optString(key);
+ if (value != null) {
+ sb.append(' ');
+ sb.append(XML.escape(key));
+ sb.append('=');
+ sb.append('"');
+ sb.append(XML.escape(value));
+ sb.append('"');
+ }
+ }
+ } else {
+ i = 1;
+ }
+
+//Emit content in body
+
+ length = ja.length();
+ if (i >= length) {
+ sb.append('/');
+ sb.append('>');
+ } else {
+ sb.append('>');
+ do {
+ object = ja.get(i);
+ i += 1;
+ if (object != null) {
+ if (object instanceof String) {
+ sb.append(XML.escape(object.toString()));
+ } else if (object instanceof JSONObject) {
+ sb.append(toString((JSONObject)object));
+ } else if (object instanceof JSONArray) {
+ sb.append(toString((JSONArray)object));
+ }
+ }
+ } while (i < length);
+ sb.append('<');
+ sb.append('/');
+ sb.append(tagName);
+ sb.append('>');
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Reverse the JSONML transformation, making an XML text from a JSONObject.
+ * The JSONObject must contain a "tagName" property. If it has children,
+ * then it must have a "childNodes" property containing an array of objects.
+ * The other properties are attributes with string values.
+ * @param jo A JSONObject.
+ * @return An XML string.
+ * @throws JSONException
+ */
+ public static String toString(JSONObject jo) throws JSONException {
+ StringBuffer sb = new StringBuffer();
+ int i;
+ JSONArray ja;
+ String key;
+ Iterator keys;
+ int length;
+ Object object;
+ String tagName;
+ String value;
+
+//Emit <tagName
+
+ tagName = jo.optString("tagName");
+ if (tagName == null) {
+ return XML.escape(jo.toString());
+ }
+ XML.noSpace(tagName);
+ tagName = XML.escape(tagName);
+ sb.append('<');
+ sb.append(tagName);
+
+//Emit the attributes
+
+ keys = jo.keys();
+ while (keys.hasNext()) {
+ key = keys.next().toString();
+ if (!"tagName".equals(key) && !"childNodes".equals(key)) {
+ XML.noSpace(key);
+ value = jo.optString(key);
+ if (value != null) {
+ sb.append(' ');
+ sb.append(XML.escape(key));
+ sb.append('=');
+ sb.append('"');
+ sb.append(XML.escape(value));
+ sb.append('"');
+ }
+ }
+ }
+
+//Emit content in body
+
+ ja = jo.optJSONArray("childNodes");
+ if (ja == null) {
+ sb.append('/');
+ sb.append('>');
+ } else {
+ sb.append('>');
+ length = ja.length();
+ for (i = 0; i < length; i += 1) {
+ object = ja.get(i);
+ if (object != null) {
+ if (object instanceof String) {
+ sb.append(XML.escape(object.toString()));
+ } else if (object instanceof JSONObject) {
+ sb.append(toString((JSONObject)object));
+ } else if (object instanceof JSONArray) {
+ sb.append(toString((JSONArray)object));
+ } else {
+ sb.append(object.toString());
+ }
+ }
+ }
+ sb.append('<');
+ sb.append('/');
+ sb.append(tagName);
+ sb.append('>');
+ }
+ return sb.toString();
+ }
+}