diff options
Diffstat (limited to 'mobileapp/src/org/json/JSONML.java')
-rwxr-xr-x | mobileapp/src/org/json/JSONML.java | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/mobileapp/src/org/json/JSONML.java b/mobileapp/src/org/json/JSONML.java new file mode 100755 index 0000000..1337182 --- /dev/null +++ b/mobileapp/src/org/json/JSONML.java @@ -0,0 +1,455 @@ +package org.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. +*/ + +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. + * @author JSON.org + * @version 2010-02-12 + */ +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) { + 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) { + +// <! + + 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"); + } + +// 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; + } + +// 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, JSONObject.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; + } + } + +// 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 ? + JSONObject.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 { + Object e; + int i; + JSONObject jo; + String k; + Iterator keys; + int length; + StringBuffer sb = new StringBuffer(); + String tagName; + String v; + +// Emit <tagName + + tagName = ja.getString(0); + XML.noSpace(tagName); + tagName = XML.escape(tagName); + sb.append('<'); + sb.append(tagName); + + e = ja.opt(1); + if (e instanceof JSONObject) { + i = 2; + jo = (JSONObject)e; + +// Emit the attributes + + keys = jo.keys(); + while (keys.hasNext()) { + k = keys.next().toString(); + XML.noSpace(k); + v = jo.optString(k); + if (v != null) { + sb.append(' '); + sb.append(XML.escape(k)); + sb.append('='); + sb.append('"'); + sb.append(XML.escape(v)); + sb.append('"'); + } + } + } else { + i = 1; + } + +//Emit content in body + + length = ja.length(); + if (i >= length) { + sb.append('/'); + sb.append('>'); + } else { + sb.append('>'); + do { + e = ja.get(i); + i += 1; + if (e != null) { + if (e instanceof String) { + sb.append(XML.escape(e.toString())); + } else if (e instanceof JSONObject) { + sb.append(toString((JSONObject)e)); + } else if (e instanceof JSONArray) { + sb.append(toString((JSONArray)e)); + } + } + } 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(); + Object e; + int i; + JSONArray ja; + String k; + Iterator keys; + int len; + String tagName; + String v; + +//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()) { + k = keys.next().toString(); + if (!k.equals("tagName") && !k.equals("childNodes")) { + XML.noSpace(k); + v = jo.optString(k); + if (v != null) { + sb.append(' '); + sb.append(XML.escape(k)); + sb.append('='); + sb.append('"'); + sb.append(XML.escape(v)); + sb.append('"'); + } + } + } + +//Emit content in body + + ja = jo.optJSONArray("childNodes"); + if (ja == null) { + sb.append('/'); + sb.append('>'); + } else { + sb.append('>'); + len = ja.length(); + for (i = 0; i < len; i += 1) { + e = ja.get(i); + if (e != null) { + if (e instanceof String) { + sb.append(XML.escape(e.toString())); + } else if (e instanceof JSONObject) { + sb.append(toString((JSONObject)e)); + } else if (e instanceof JSONArray) { + sb.append(toString((JSONArray)e)); + } + } + } + sb.append('<'); + sb.append('/'); + sb.append(tagName); + sb.append('>'); + } + return sb.toString(); + } +}
\ No newline at end of file |