root / src / org / json / JSONML.java @ 4bf05cad
History | View | Annotate | Download (14.3 kB)
1 | 14ad7326 | pastith | package org.json; |
---|---|---|---|
2 | 14ad7326 | pastith | |
3 | 14ad7326 | pastith | /*
|
4 | 14ad7326 | pastith | Copyright (c) 2008 JSON.org
|
5 | 14ad7326 | pastith | |
6 | 14ad7326 | pastith | Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 14ad7326 | pastith | of this software and associated documentation files (the "Software"), to deal
|
8 | 14ad7326 | pastith | in the Software without restriction, including without limitation the rights
|
9 | 14ad7326 | pastith | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 14ad7326 | pastith | copies of the Software, and to permit persons to whom the Software is
|
11 | 14ad7326 | pastith | furnished to do so, subject to the following conditions:
|
12 | 14ad7326 | pastith | |
13 | 14ad7326 | pastith | The above copyright notice and this permission notice shall be included in all
|
14 | 14ad7326 | pastith | copies or substantial portions of the Software.
|
15 | 14ad7326 | pastith | |
16 | 14ad7326 | pastith | The Software shall be used for Good, not Evil.
|
17 | 14ad7326 | pastith | |
18 | 14ad7326 | pastith | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19 | 14ad7326 | pastith | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20 | 14ad7326 | pastith | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21 | 14ad7326 | pastith | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22 | 14ad7326 | pastith | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23 | 14ad7326 | pastith | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
24 | 14ad7326 | pastith | SOFTWARE.
|
25 | 14ad7326 | pastith | */
|
26 | 14ad7326 | pastith | |
27 | 14ad7326 | pastith | import java.util.Iterator; |
28 | 14ad7326 | pastith | |
29 | 14ad7326 | pastith | |
30 | 14ad7326 | pastith | /**
|
31 | 14ad7326 | pastith | * This provides static methods to convert an XML text into a JSONArray or
|
32 | 14ad7326 | pastith | * JSONObject, and to covert a JSONArray or JSONObject into an XML text using
|
33 | 14ad7326 | pastith | * the JsonML transform.
|
34 | 14ad7326 | pastith | * @author JSON.org
|
35 | 14ad7326 | pastith | * @version 2008-09-18
|
36 | 14ad7326 | pastith | */
|
37 | 14ad7326 | pastith | public class JSONML { |
38 | 14ad7326 | pastith | |
39 | 14ad7326 | pastith | /**
|
40 | 14ad7326 | pastith | * Parse XML values and store them in a JSONArray.
|
41 | 14ad7326 | pastith | * @param x The XMLTokener containing the source string.
|
42 | 14ad7326 | pastith | * @param arrayForm true if array form, false if object form.
|
43 | 14ad7326 | pastith | * @param ja The JSONArray that is containing the current tag or null
|
44 | 14ad7326 | pastith | * if we are at the outermost level.
|
45 | 14ad7326 | pastith | * @return A JSONArray if the value is the outermost tag, otherwise null.
|
46 | 14ad7326 | pastith | * @throws JSONException
|
47 | 14ad7326 | pastith | */
|
48 | 14ad7326 | pastith | private static Object parse(XMLTokener x, boolean arrayForm, |
49 | 14ad7326 | pastith | JSONArray ja) throws JSONException {
|
50 | 14ad7326 | pastith | String attribute;
|
51 | 14ad7326 | pastith | char c;
|
52 | 14ad7326 | pastith | String closeTag = null; |
53 | 14ad7326 | pastith | int i;
|
54 | 14ad7326 | pastith | JSONArray newja = null;
|
55 | 14ad7326 | pastith | JSONObject newjo = null;
|
56 | 14ad7326 | pastith | Object token;
|
57 | 14ad7326 | pastith | String tagName = null; |
58 | 14ad7326 | pastith | |
59 | 14ad7326 | pastith | // Test for and skip past these forms:
|
60 | 14ad7326 | pastith | // <!-- ... -->
|
61 | 14ad7326 | pastith | // <![ ... ]]>
|
62 | 14ad7326 | pastith | // <! ... >
|
63 | 14ad7326 | pastith | // <? ... ?>
|
64 | 14ad7326 | pastith | |
65 | 14ad7326 | pastith | while (true) { |
66 | 14ad7326 | pastith | token = x.nextContent(); |
67 | 14ad7326 | pastith | if (token == XML.LT) {
|
68 | 14ad7326 | pastith | token = x.nextToken(); |
69 | 14ad7326 | pastith | if (token instanceof Character) { |
70 | 14ad7326 | pastith | if (token == XML.SLASH) {
|
71 | 14ad7326 | pastith | |
72 | 14ad7326 | pastith | // Close tag </
|
73 | 14ad7326 | pastith | |
74 | 14ad7326 | pastith | token = x.nextToken(); |
75 | 14ad7326 | pastith | if (!(token instanceof String)) { |
76 | 14ad7326 | pastith | throw new JSONException( |
77 | 14ad7326 | pastith | "Expected a closing name instead of '" +
|
78 | 14ad7326 | pastith | token + "'.");
|
79 | 14ad7326 | pastith | } |
80 | 14ad7326 | pastith | if (x.nextToken() != XML.GT) {
|
81 | 14ad7326 | pastith | throw x.syntaxError("Misshaped close tag"); |
82 | 14ad7326 | pastith | } |
83 | 14ad7326 | pastith | return token;
|
84 | 14ad7326 | pastith | } else if (token == XML.BANG) { |
85 | 14ad7326 | pastith | |
86 | 14ad7326 | pastith | // <!
|
87 | 14ad7326 | pastith | |
88 | 14ad7326 | pastith | c = x.next(); |
89 | 14ad7326 | pastith | if (c == '-') { |
90 | 14ad7326 | pastith | if (x.next() == '-') { |
91 | 14ad7326 | pastith | x.skipPast("-->");
|
92 | 14ad7326 | pastith | } |
93 | 14ad7326 | pastith | x.back(); |
94 | 14ad7326 | pastith | } else if (c == '[') { |
95 | 14ad7326 | pastith | token = x.nextToken(); |
96 | 14ad7326 | pastith | if (token.equals("CDATA") && x.next() == '[') { |
97 | 14ad7326 | pastith | if (ja != null) { |
98 | 14ad7326 | pastith | ja.put(x.nextCDATA()); |
99 | 14ad7326 | pastith | } |
100 | 14ad7326 | pastith | } else {
|
101 | 14ad7326 | pastith | throw x.syntaxError("Expected 'CDATA['"); |
102 | 14ad7326 | pastith | } |
103 | 14ad7326 | pastith | } else {
|
104 | 14ad7326 | pastith | i = 1;
|
105 | 14ad7326 | pastith | do {
|
106 | 14ad7326 | pastith | token = x.nextMeta(); |
107 | 14ad7326 | pastith | if (token == null) { |
108 | 14ad7326 | pastith | throw x.syntaxError("Missing '>' after '<!'."); |
109 | 14ad7326 | pastith | } else if (token == XML.LT) { |
110 | 14ad7326 | pastith | i += 1;
|
111 | 14ad7326 | pastith | } else if (token == XML.GT) { |
112 | 14ad7326 | pastith | i -= 1;
|
113 | 14ad7326 | pastith | } |
114 | 14ad7326 | pastith | } while (i > 0); |
115 | 14ad7326 | pastith | } |
116 | 14ad7326 | pastith | } else if (token == XML.QUEST) { |
117 | 14ad7326 | pastith | |
118 | 14ad7326 | pastith | // <?
|
119 | 14ad7326 | pastith | |
120 | 14ad7326 | pastith | x.skipPast("?>");
|
121 | 14ad7326 | pastith | } else {
|
122 | 14ad7326 | pastith | throw x.syntaxError("Misshaped tag"); |
123 | 14ad7326 | pastith | } |
124 | 14ad7326 | pastith | |
125 | 14ad7326 | pastith | // Open tag <
|
126 | 14ad7326 | pastith | |
127 | 14ad7326 | pastith | } else {
|
128 | 14ad7326 | pastith | if (!(token instanceof String)) { |
129 | 14ad7326 | pastith | throw x.syntaxError("Bad tagName '" + token + "'."); |
130 | 14ad7326 | pastith | } |
131 | 14ad7326 | pastith | tagName = (String)token;
|
132 | 14ad7326 | pastith | newja = new JSONArray();
|
133 | 14ad7326 | pastith | newjo = new JSONObject();
|
134 | 14ad7326 | pastith | if (arrayForm) {
|
135 | 14ad7326 | pastith | newja.put(tagName); |
136 | 14ad7326 | pastith | if (ja != null) { |
137 | 14ad7326 | pastith | ja.put(newja); |
138 | 14ad7326 | pastith | } |
139 | 14ad7326 | pastith | } else {
|
140 | 14ad7326 | pastith | newjo.put("tagName", tagName);
|
141 | 14ad7326 | pastith | if (ja != null) { |
142 | 14ad7326 | pastith | ja.put(newjo); |
143 | 14ad7326 | pastith | } |
144 | 14ad7326 | pastith | } |
145 | 14ad7326 | pastith | token = null;
|
146 | 14ad7326 | pastith | for (;;) {
|
147 | 14ad7326 | pastith | if (token == null) { |
148 | 14ad7326 | pastith | token = x.nextToken(); |
149 | 14ad7326 | pastith | } |
150 | 14ad7326 | pastith | if (token == null) { |
151 | 14ad7326 | pastith | throw x.syntaxError("Misshaped tag"); |
152 | 14ad7326 | pastith | } |
153 | 14ad7326 | pastith | if (!(token instanceof String)) { |
154 | 14ad7326 | pastith | break;
|
155 | 14ad7326 | pastith | } |
156 | 14ad7326 | pastith | |
157 | 14ad7326 | pastith | // attribute = value
|
158 | 14ad7326 | pastith | |
159 | 14ad7326 | pastith | attribute = (String)token;
|
160 | 14ad7326 | pastith | if (!arrayForm && (attribute == "tagName" || attribute == "childNode")) { |
161 | 14ad7326 | pastith | throw x.syntaxError("Reserved attribute."); |
162 | 14ad7326 | pastith | } |
163 | 14ad7326 | pastith | token = x.nextToken(); |
164 | 14ad7326 | pastith | if (token == XML.EQ) {
|
165 | 14ad7326 | pastith | token = x.nextToken(); |
166 | 14ad7326 | pastith | if (!(token instanceof String)) { |
167 | 14ad7326 | pastith | throw x.syntaxError("Missing value"); |
168 | 14ad7326 | pastith | } |
169 | 14ad7326 | pastith | newjo.accumulate(attribute, JSONObject.stringToValue((String)token));
|
170 | 14ad7326 | pastith | token = null;
|
171 | 14ad7326 | pastith | } else {
|
172 | 14ad7326 | pastith | newjo.accumulate(attribute, "");
|
173 | 14ad7326 | pastith | } |
174 | 14ad7326 | pastith | } |
175 | 14ad7326 | pastith | if (arrayForm && newjo.length() > 0) { |
176 | 14ad7326 | pastith | newja.put(newjo); |
177 | 14ad7326 | pastith | } |
178 | 14ad7326 | pastith | |
179 | 14ad7326 | pastith | // Empty tag <.../>
|
180 | 14ad7326 | pastith | |
181 | 14ad7326 | pastith | if (token == XML.SLASH) {
|
182 | 14ad7326 | pastith | if (x.nextToken() != XML.GT) {
|
183 | 14ad7326 | pastith | throw x.syntaxError("Misshaped tag"); |
184 | 14ad7326 | pastith | } |
185 | 14ad7326 | pastith | if (ja == null) { |
186 | 14ad7326 | pastith | return arrayForm ? newja : newjo;
|
187 | 14ad7326 | pastith | } |
188 | 14ad7326 | pastith | |
189 | 14ad7326 | pastith | // Content, between <...> and </...>
|
190 | 14ad7326 | pastith | |
191 | 14ad7326 | pastith | } else {
|
192 | 14ad7326 | pastith | if (token != XML.GT) {
|
193 | 14ad7326 | pastith | throw x.syntaxError("Misshaped tag"); |
194 | 14ad7326 | pastith | } |
195 | 14ad7326 | pastith | closeTag = (String)parse(x, arrayForm, newja);
|
196 | 14ad7326 | pastith | if (closeTag != null) { |
197 | 14ad7326 | pastith | if (!closeTag.equals(tagName)) {
|
198 | 14ad7326 | pastith | throw x.syntaxError("Mismatched '" + tagName + |
199 | 14ad7326 | pastith | "' and '" + closeTag + "'"); |
200 | 14ad7326 | pastith | } |
201 | 14ad7326 | pastith | tagName = null;
|
202 | 14ad7326 | pastith | if (!arrayForm && newja.length() > 0) { |
203 | 14ad7326 | pastith | newjo.put("childNodes", newja);
|
204 | 14ad7326 | pastith | } |
205 | 14ad7326 | pastith | if (ja == null) { |
206 | 14ad7326 | pastith | return arrayForm ? newja : newjo;
|
207 | 14ad7326 | pastith | } |
208 | 14ad7326 | pastith | } |
209 | 14ad7326 | pastith | } |
210 | 14ad7326 | pastith | } |
211 | 14ad7326 | pastith | } else {
|
212 | 14ad7326 | pastith | if (ja != null) { |
213 | 14ad7326 | pastith | ja.put(token instanceof String ? |
214 | 14ad7326 | pastith | JSONObject.stringToValue((String)token) : token);
|
215 | 14ad7326 | pastith | } |
216 | 14ad7326 | pastith | } |
217 | 14ad7326 | pastith | } |
218 | 14ad7326 | pastith | } |
219 | 14ad7326 | pastith | |
220 | 14ad7326 | pastith | |
221 | 14ad7326 | pastith | /**
|
222 | 14ad7326 | pastith | * Convert a well-formed (but not necessarily valid) XML string into a
|
223 | 14ad7326 | pastith | * JSONArray using the JsonML transform. Each XML tag is represented as
|
224 | 14ad7326 | pastith | * a JSONArray in which the first element is the tag name. If the tag has
|
225 | 14ad7326 | pastith | * attributes, then the second element will be JSONObject containing the
|
226 | 14ad7326 | pastith | * name/value pairs. If the tag contains children, then strings and
|
227 | 14ad7326 | pastith | * JSONArrays will represent the child tags.
|
228 | 14ad7326 | pastith | * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
229 | 14ad7326 | pastith | * @param string The source string.
|
230 | 14ad7326 | pastith | * @return A JSONArray containing the structured data from the XML string.
|
231 | 14ad7326 | pastith | * @throws JSONException
|
232 | 14ad7326 | pastith | */
|
233 | 14ad7326 | pastith | public static JSONArray toJSONArray(String string) throws JSONException { |
234 | 14ad7326 | pastith | return toJSONArray(new XMLTokener(string)); |
235 | 14ad7326 | pastith | } |
236 | 14ad7326 | pastith | |
237 | 14ad7326 | pastith | |
238 | 14ad7326 | pastith | /**
|
239 | 14ad7326 | pastith | * Convert a well-formed (but not necessarily valid) XML string into a
|
240 | 14ad7326 | pastith | * JSONArray using the JsonML transform. Each XML tag is represented as
|
241 | 14ad7326 | pastith | * a JSONArray in which the first element is the tag name. If the tag has
|
242 | 14ad7326 | pastith | * attributes, then the second element will be JSONObject containing the
|
243 | 14ad7326 | pastith | * name/value pairs. If the tag contains children, then strings and
|
244 | 14ad7326 | pastith | * JSONArrays will represent the child content and tags.
|
245 | 14ad7326 | pastith | * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
246 | 14ad7326 | pastith | * @param x An XMLTokener.
|
247 | 14ad7326 | pastith | * @return A JSONArray containing the structured data from the XML string.
|
248 | 14ad7326 | pastith | * @throws JSONException
|
249 | 14ad7326 | pastith | */
|
250 | 14ad7326 | pastith | public static JSONArray toJSONArray(XMLTokener x) throws JSONException { |
251 | 14ad7326 | pastith | return (JSONArray)parse(x, true, null); |
252 | 14ad7326 | pastith | } |
253 | 14ad7326 | pastith | |
254 | 14ad7326 | pastith | |
255 | 14ad7326 | pastith | |
256 | 14ad7326 | pastith | /**
|
257 | 14ad7326 | pastith | * Convert a well-formed (but not necessarily valid) XML string into a
|
258 | 14ad7326 | pastith | * JSONObject using the JsonML transform. Each XML tag is represented as
|
259 | 14ad7326 | pastith | * a JSONObject with a "tagName" property. If the tag has attributes, then
|
260 | 14ad7326 | pastith | * the attributes will be in the JSONObject as properties. If the tag
|
261 | 14ad7326 | pastith | * contains children, the object will have a "childNodes" property which
|
262 | 14ad7326 | pastith | * will be an array of strings and JsonML JSONObjects.
|
263 | 14ad7326 | pastith | |
264 | 14ad7326 | pastith | * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
265 | 14ad7326 | pastith | * @param x An XMLTokener of the XML source text.
|
266 | 14ad7326 | pastith | * @return A JSONObject containing the structured data from the XML string.
|
267 | 14ad7326 | pastith | * @throws JSONException
|
268 | 14ad7326 | pastith | */
|
269 | 14ad7326 | pastith | public static JSONObject toJSONObject(XMLTokener x) throws JSONException { |
270 | 14ad7326 | pastith | return (JSONObject)parse(x, false, null); |
271 | 14ad7326 | pastith | } |
272 | 14ad7326 | pastith | /**
|
273 | 14ad7326 | pastith | * Convert a well-formed (but not necessarily valid) XML string into a
|
274 | 14ad7326 | pastith | * JSONObject using the JsonML transform. Each XML tag is represented as
|
275 | 14ad7326 | pastith | * a JSONObject with a "tagName" property. If the tag has attributes, then
|
276 | 14ad7326 | pastith | * the attributes will be in the JSONObject as properties. If the tag
|
277 | 14ad7326 | pastith | * contains children, the object will have a "childNodes" property which
|
278 | 14ad7326 | pastith | * will be an array of strings and JsonML JSONObjects.
|
279 | 14ad7326 | pastith | |
280 | 14ad7326 | pastith | * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
281 | 14ad7326 | pastith | * @param string The XML source text.
|
282 | 14ad7326 | pastith | * @return A JSONObject containing the structured data from the XML string.
|
283 | 14ad7326 | pastith | * @throws JSONException
|
284 | 14ad7326 | pastith | */
|
285 | 14ad7326 | pastith | public static JSONObject toJSONObject(String string) throws JSONException { |
286 | 14ad7326 | pastith | return toJSONObject(new XMLTokener(string)); |
287 | 14ad7326 | pastith | } |
288 | 14ad7326 | pastith | |
289 | 14ad7326 | pastith | |
290 | 14ad7326 | pastith | /**
|
291 | 14ad7326 | pastith | * Reverse the JSONML transformation, making an XML text from a JSONArray.
|
292 | 14ad7326 | pastith | * @param ja A JSONArray.
|
293 | 14ad7326 | pastith | * @return An XML string.
|
294 | 14ad7326 | pastith | * @throws JSONException
|
295 | 14ad7326 | pastith | */
|
296 | 14ad7326 | pastith | public static String toString(JSONArray ja) throws JSONException { |
297 | 14ad7326 | pastith | Object e;
|
298 | 14ad7326 | pastith | int i;
|
299 | 14ad7326 | pastith | JSONObject jo; |
300 | 14ad7326 | pastith | String k;
|
301 | 14ad7326 | pastith | Iterator keys;
|
302 | 14ad7326 | pastith | int length;
|
303 | 14ad7326 | pastith | StringBuffer sb = new StringBuffer(); |
304 | 14ad7326 | pastith | String tagName;
|
305 | 14ad7326 | pastith | String v;
|
306 | 14ad7326 | pastith | |
307 | 14ad7326 | pastith | // Emit <tagName
|
308 | 14ad7326 | pastith | |
309 | 14ad7326 | pastith | tagName = ja.getString(0);
|
310 | 14ad7326 | pastith | XML.noSpace(tagName); |
311 | 14ad7326 | pastith | tagName = XML.escape(tagName); |
312 | 14ad7326 | pastith | sb.append('<');
|
313 | 14ad7326 | pastith | sb.append(tagName); |
314 | 14ad7326 | pastith | |
315 | 14ad7326 | pastith | e = ja.opt(1);
|
316 | 14ad7326 | pastith | if (e instanceof JSONObject) { |
317 | 14ad7326 | pastith | i = 2;
|
318 | 14ad7326 | pastith | jo = (JSONObject)e; |
319 | 14ad7326 | pastith | |
320 | 14ad7326 | pastith | // Emit the attributes
|
321 | 14ad7326 | pastith | |
322 | 14ad7326 | pastith | keys = jo.keys(); |
323 | 14ad7326 | pastith | while (keys.hasNext()) {
|
324 | 14ad7326 | pastith | k = keys.next().toString(); |
325 | 14ad7326 | pastith | XML.noSpace(k); |
326 | 14ad7326 | pastith | v = jo.optString(k); |
327 | 14ad7326 | pastith | if (v != null) { |
328 | 14ad7326 | pastith | sb.append(' ');
|
329 | 14ad7326 | pastith | sb.append(XML.escape(k)); |
330 | 14ad7326 | pastith | sb.append('=');
|
331 | 14ad7326 | pastith | sb.append('"');
|
332 | 14ad7326 | pastith | sb.append(XML.escape(v)); |
333 | 14ad7326 | pastith | sb.append('"');
|
334 | 14ad7326 | pastith | } |
335 | 14ad7326 | pastith | } |
336 | 14ad7326 | pastith | } else {
|
337 | 14ad7326 | pastith | i = 1;
|
338 | 14ad7326 | pastith | } |
339 | 14ad7326 | pastith | |
340 | 14ad7326 | pastith | //Emit content in body
|
341 | 14ad7326 | pastith | |
342 | 14ad7326 | pastith | length = ja.length(); |
343 | 14ad7326 | pastith | if (i >= length) {
|
344 | 14ad7326 | pastith | sb.append('/');
|
345 | 14ad7326 | pastith | sb.append('>');
|
346 | 14ad7326 | pastith | } else {
|
347 | 14ad7326 | pastith | sb.append('>');
|
348 | 14ad7326 | pastith | do {
|
349 | 14ad7326 | pastith | e = ja.get(i); |
350 | 14ad7326 | pastith | i += 1;
|
351 | 14ad7326 | pastith | if (e != null) { |
352 | 14ad7326 | pastith | if (e instanceof String) { |
353 | 14ad7326 | pastith | sb.append(XML.escape(e.toString())); |
354 | 14ad7326 | pastith | } else if (e instanceof JSONObject) { |
355 | 14ad7326 | pastith | sb.append(toString((JSONObject)e)); |
356 | 14ad7326 | pastith | } else if (e instanceof JSONArray) { |
357 | 14ad7326 | pastith | sb.append(toString((JSONArray)e)); |
358 | 14ad7326 | pastith | } |
359 | 14ad7326 | pastith | } |
360 | 14ad7326 | pastith | } while (i < length);
|
361 | 14ad7326 | pastith | sb.append('<');
|
362 | 14ad7326 | pastith | sb.append('/');
|
363 | 14ad7326 | pastith | sb.append(tagName); |
364 | 14ad7326 | pastith | sb.append('>');
|
365 | 14ad7326 | pastith | } |
366 | 14ad7326 | pastith | return sb.toString();
|
367 | 14ad7326 | pastith | } |
368 | 14ad7326 | pastith | |
369 | 14ad7326 | pastith | /**
|
370 | 14ad7326 | pastith | * Reverse the JSONML transformation, making an XML text from a JSONObject.
|
371 | 14ad7326 | pastith | * The JSONObject must contain a "tagName" property. If it has children,
|
372 | 14ad7326 | pastith | * then it must have a "childNodes" property containing an array of objects.
|
373 | 14ad7326 | pastith | * The other properties are attributes with string values.
|
374 | 14ad7326 | pastith | * @param jo A JSONObject.
|
375 | 14ad7326 | pastith | * @return An XML string.
|
376 | 14ad7326 | pastith | * @throws JSONException
|
377 | 14ad7326 | pastith | */
|
378 | 14ad7326 | pastith | public static String toString(JSONObject jo) throws JSONException { |
379 | 14ad7326 | pastith | StringBuffer sb = new StringBuffer(); |
380 | 14ad7326 | pastith | Object e;
|
381 | 14ad7326 | pastith | int i;
|
382 | 14ad7326 | pastith | JSONArray ja; |
383 | 14ad7326 | pastith | String k;
|
384 | 14ad7326 | pastith | Iterator keys;
|
385 | 14ad7326 | pastith | int len;
|
386 | 14ad7326 | pastith | String tagName;
|
387 | 14ad7326 | pastith | String v;
|
388 | 14ad7326 | pastith | |
389 | 14ad7326 | pastith | //Emit <tagName
|
390 | 14ad7326 | pastith | |
391 | 14ad7326 | pastith | tagName = jo.optString("tagName");
|
392 | 14ad7326 | pastith | if (tagName == null) { |
393 | 14ad7326 | pastith | return XML.escape(jo.toString());
|
394 | 14ad7326 | pastith | } |
395 | 14ad7326 | pastith | XML.noSpace(tagName); |
396 | 14ad7326 | pastith | tagName = XML.escape(tagName); |
397 | 14ad7326 | pastith | sb.append('<');
|
398 | 14ad7326 | pastith | sb.append(tagName); |
399 | 14ad7326 | pastith | |
400 | 14ad7326 | pastith | //Emit the attributes
|
401 | 14ad7326 | pastith | |
402 | 14ad7326 | pastith | keys = jo.keys(); |
403 | 14ad7326 | pastith | while (keys.hasNext()) {
|
404 | 14ad7326 | pastith | k = keys.next().toString(); |
405 | 14ad7326 | pastith | if (!k.equals("tagName") && !k.equals("childNodes")) { |
406 | 14ad7326 | pastith | XML.noSpace(k); |
407 | 14ad7326 | pastith | v = jo.optString(k); |
408 | 14ad7326 | pastith | if (v != null) { |
409 | 14ad7326 | pastith | sb.append(' ');
|
410 | 14ad7326 | pastith | sb.append(XML.escape(k)); |
411 | 14ad7326 | pastith | sb.append('=');
|
412 | 14ad7326 | pastith | sb.append('"');
|
413 | 14ad7326 | pastith | sb.append(XML.escape(v)); |
414 | 14ad7326 | pastith | sb.append('"');
|
415 | 14ad7326 | pastith | } |
416 | 14ad7326 | pastith | } |
417 | 14ad7326 | pastith | } |
418 | 14ad7326 | pastith | |
419 | 14ad7326 | pastith | //Emit content in body
|
420 | 14ad7326 | pastith | |
421 | 14ad7326 | pastith | ja = jo.optJSONArray("childNodes");
|
422 | 14ad7326 | pastith | if (ja == null) { |
423 | 14ad7326 | pastith | sb.append('/');
|
424 | 14ad7326 | pastith | sb.append('>');
|
425 | 14ad7326 | pastith | } else {
|
426 | 14ad7326 | pastith | sb.append('>');
|
427 | 14ad7326 | pastith | len = ja.length(); |
428 | 14ad7326 | pastith | for (i = 0; i < len; i += 1) { |
429 | 14ad7326 | pastith | e = ja.get(i); |
430 | 14ad7326 | pastith | if (e != null) { |
431 | 14ad7326 | pastith | if (e instanceof String) { |
432 | 14ad7326 | pastith | sb.append(XML.escape(e.toString())); |
433 | 14ad7326 | pastith | } else if (e instanceof JSONObject) { |
434 | 14ad7326 | pastith | sb.append(toString((JSONObject)e)); |
435 | 14ad7326 | pastith | } else if (e instanceof JSONArray) { |
436 | 14ad7326 | pastith | sb.append(toString((JSONArray)e)); |
437 | 14ad7326 | pastith | } |
438 | 14ad7326 | pastith | } |
439 | 14ad7326 | pastith | } |
440 | 14ad7326 | pastith | sb.append('<');
|
441 | 14ad7326 | pastith | sb.append('/');
|
442 | 14ad7326 | pastith | sb.append(tagName); |
443 | 14ad7326 | pastith | sb.append('>');
|
444 | 14ad7326 | pastith | } |
445 | 14ad7326 | pastith | return sb.toString();
|
446 | 14ad7326 | pastith | } |
447 | 14ad7326 | pastith | } |