Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
JSONML | 35 | 202 | 76 |
1 | package org.json; | |
2 | ||
3 | /* | |
4 | Copyright (c) 2008 JSON.org | |
5 | ||
6 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | of this software and associated documentation files (the "Software"), to deal | |
8 | in the Software without restriction, including without limitation the rights | |
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | copies of the Software, and to permit persons to whom the Software is | |
11 | furnished to do so, subject to the following conditions: | |
12 | ||
13 | The above copyright notice and this permission notice shall be included in all | |
14 | copies or substantial portions of the Software. | |
15 | ||
16 | The Software shall be used for Good, not Evil. | |
17 | ||
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
24 | SOFTWARE. | |
25 | */ | |
26 | ||
27 | /** | |
28 | * This provides static methods to convert an XML text into a JSONArray or | |
29 | * JSONObject, and to covert a JSONArray or JSONObject into an XML text using | |
30 | * the JsonML transform. | |
31 | * | |
32 | * @author JSON.org | |
33 | * @version 2016-01-30 | |
34 | */ | |
35 | public class JSONML | |
36 | { | |
37 | /** | |
38 | * Parse XML values and store them in a JSONArray. | |
39 | * | |
40 | * @param x | |
41 | * The XMLTokener containing the source string. | |
42 | * @param arrayForm | |
43 | * true if array form, false if object form. | |
44 | * @param ja | |
45 | * The JSONArray that is containing the current tag or null if we are | |
46 | * at the outermost level. | |
47 | * @param keepStrings | |
48 | * Don't type-convert text nodes and attribute values | |
49 | * @return A JSONArray if the value is the outermost tag, otherwise null. | |
50 | * @throws JSONException | |
51 | */ | |
52 | 0 | private static Object parse(XMLTokener x, boolean arrayForm, JSONArray ja, |
53 | boolean keepStrings) throws JSONException | |
54 | { | |
55 | 0 | String attribute; |
56 | 0 | char c; |
57 | 0 | String closeTag = null; |
58 | 0 | int i; |
59 | 0 | JSONArray newja = null; |
60 | 0 | JSONObject newjo = null; |
61 | 0 | Object token; |
62 | 0 | String tagName = null; |
63 | ||
64 | // Test for and skip past these forms: | |
65 | // <!-- ... --> | |
66 | // <![ ... ]]> | |
67 | // <! ... > | |
68 | // <? ... ?> | |
69 | ||
70 | 0 | while (true) |
71 | { | |
72 | 0 | if (!x.more()) |
73 | { | |
74 | 0 | throw x.syntaxError("Bad XML"); |
75 | } | |
76 | 0 | token = x.nextContent(); |
77 | 0 | if (token == XML.LT) |
78 | { | |
79 | 0 | token = x.nextToken(); |
80 | 0 | if (token instanceof Character) |
81 | { | |
82 | 0 | if (token == XML.SLASH) |
83 | { | |
84 | ||
85 | // Close tag </ | |
86 | ||
87 | 0 | token = x.nextToken(); |
88 | 0 | if (!(token instanceof String)) |
89 | { | |
90 | 0 | throw new JSONException("Expected a closing name instead of '" |
91 | + token + "'."); | |
92 | } | |
93 | 0 | if (x.nextToken() != XML.GT) |
94 | { | |
95 | 0 | throw x.syntaxError("Misshaped close tag"); |
96 | } | |
97 | 0 | return token; |
98 | } | |
99 | 0 | else if (token == XML.BANG) |
100 | { | |
101 | ||
102 | // <! | |
103 | ||
104 | 0 | c = x.next(); |
105 | 0 | if (c == '-') |
106 | { | |
107 | 0 | if (x.next() == '-') |
108 | { | |
109 | 0 | x.skipPast("-->"); |
110 | } | |
111 | else | |
112 | { | |
113 | 0 | x.back(); |
114 | } | |
115 | } | |
116 | 0 | else if (c == '[') |
117 | { | |
118 | 0 | token = x.nextToken(); |
119 | 0 | if (token.equals("CDATA") && x.next() == '[') |
120 | { | |
121 | 0 | if (ja != null) |
122 | { | |
123 | 0 | ja.put(x.nextCDATA()); |
124 | } | |
125 | } | |
126 | else | |
127 | { | |
128 | 0 | throw x.syntaxError("Expected 'CDATA['"); |
129 | } | |
130 | } | |
131 | else | |
132 | { | |
133 | 0 | i = 1; |
134 | 0 | do |
135 | { | |
136 | 0 | token = x.nextMeta(); |
137 | 0 | if (token == null) |
138 | { | |
139 | 0 | throw x.syntaxError("Missing '>' after '<!'."); |
140 | } | |
141 | 0 | else if (token == XML.LT) |
142 | { | |
143 | 0 | i += 1; |
144 | } | |
145 | 0 | else if (token == XML.GT) |
146 | { | |
147 | 0 | i -= 1; |
148 | } | |
149 | 0 | } while (i > 0); |
150 | } | |
151 | } | |
152 | 0 | else if (token == XML.QUEST) |
153 | { | |
154 | ||
155 | // <? | |
156 | ||
157 | 0 | x.skipPast("?>"); |
158 | } | |
159 | else | |
160 | { | |
161 | 0 | throw x.syntaxError("Misshaped tag"); |
162 | } | |
163 | ||
164 | // Open tag < | |
165 | ||
166 | } | |
167 | else | |
168 | { | |
169 | 0 | if (!(token instanceof String)) |
170 | { | |
171 | 0 | throw x.syntaxError("Bad tagName '" + token + "'."); |
172 | } | |
173 | 0 | tagName = (String) token; |
174 | 0 | newja = new JSONArray(); |
175 | 0 | newjo = new JSONObject(); |
176 | 0 | if (arrayForm) |
177 | { | |
178 | 0 | newja.put(tagName); |
179 | 0 | if (ja != null) |
180 | { | |
181 | 0 | ja.put(newja); |
182 | } | |
183 | } | |
184 | else | |
185 | { | |
186 | 0 | newjo.put("tagName", tagName); |
187 | 0 | if (ja != null) |
188 | { | |
189 | 0 | ja.put(newjo); |
190 | } | |
191 | } | |
192 | 0 | token = null; |
193 | 0 | for (;;) |
194 | { | |
195 | 0 | if (token == null) |
196 | { | |
197 | 0 | token = x.nextToken(); |
198 | } | |
199 | 0 | if (token == null) |
200 | { | |
201 | 0 | throw x.syntaxError("Misshaped tag"); |
202 | } | |
203 | 0 | if (!(token instanceof String)) |
204 | { | |
205 | 0 | break; |
206 | } | |
207 | ||
208 | // attribute = value | |
209 | ||
210 | 0 | attribute = (String) token; |
211 | 0 | if (!arrayForm && ("tagName".equals(attribute) |
212 | || "childNode".equals(attribute))) | |
213 | { | |
214 | 0 | throw x.syntaxError("Reserved attribute."); |
215 | } | |
216 | 0 | token = x.nextToken(); |
217 | 0 | if (token == XML.EQ) |
218 | { | |
219 | 0 | token = x.nextToken(); |
220 | 0 | if (!(token instanceof String)) |
221 | { | |
222 | 0 | throw x.syntaxError("Missing value"); |
223 | } | |
224 | 0 | newjo.accumulate(attribute, keepStrings ? ((String) token) |
225 | : XML.stringToValue((String) token)); | |
226 | 0 | token = null; |
227 | } | |
228 | else | |
229 | { | |
230 | 0 | newjo.accumulate(attribute, ""); |
231 | } | |
232 | } | |
233 | 0 | if (arrayForm && newjo.length() > 0) |
234 | { | |
235 | 0 | newja.put(newjo); |
236 | } | |
237 | ||
238 | // Empty tag <.../> | |
239 | ||
240 | 0 | if (token == XML.SLASH) |
241 | { | |
242 | 0 | if (x.nextToken() != XML.GT) |
243 | { | |
244 | 0 | throw x.syntaxError("Misshaped tag"); |
245 | } | |
246 | 0 | if (ja == null) |
247 | { | |
248 | 0 | if (arrayForm) |
249 | { | |
250 | 0 | return newja; |
251 | } | |
252 | 0 | return newjo; |
253 | } | |
254 | ||
255 | // Content, between <...> and </...> | |
256 | ||
257 | } | |
258 | else | |
259 | { | |
260 | 0 | if (token != XML.GT) |
261 | { | |
262 | 0 | throw x.syntaxError("Misshaped tag"); |
263 | } | |
264 | 0 | closeTag = (String) parse(x, arrayForm, newja, keepStrings); |
265 | 0 | if (closeTag != null) |
266 | { | |
267 | 0 | if (!closeTag.equals(tagName)) |
268 | { | |
269 | 0 | throw x.syntaxError("Mismatched '" + tagName + "' and '" |
270 | + closeTag + "'"); | |
271 | } | |
272 | 0 | tagName = null; |
273 | 0 | if (!arrayForm && newja.length() > 0) |
274 | { | |
275 | 0 | newjo.put("childNodes", newja); |
276 | } | |
277 | 0 | if (ja == null) |
278 | { | |
279 | 0 | if (arrayForm) |
280 | { | |
281 | 0 | return newja; |
282 | } | |
283 | 0 | return newjo; |
284 | } | |
285 | } | |
286 | } | |
287 | } | |
288 | } | |
289 | else | |
290 | { | |
291 | 0 | if (ja != null) |
292 | { | |
293 | 0 | ja.put(token instanceof String |
294 | 0 | ? keepStrings ? XML.unescape((String) token) |
295 | : XML.stringToValue((String) token) | |
296 | : token); | |
297 | } | |
298 | } | |
299 | } | |
300 | } | |
301 | ||
302 | /** | |
303 | * Convert a well-formed (but not necessarily valid) XML string into a | |
304 | * JSONArray using the JsonML transform. Each XML tag is represented as a | |
305 | * JSONArray in which the first element is the tag name. If the tag has | |
306 | * attributes, then the second element will be JSONObject containing the | |
307 | * name/value pairs. If the tag contains children, then strings and JSONArrays | |
308 | * will represent the child tags. Comments, prologs, DTDs, and | |
309 | * <code><[ [ ]]></code> are ignored. | |
310 | * | |
311 | * @param string | |
312 | * The source string. | |
313 | * @return A JSONArray containing the structured data from the XML string. | |
314 | * @throws JSONException | |
315 | * Thrown on error converting to a JSONArray | |
316 | */ | |
317 | 0 | public static JSONArray toJSONArray(String string) throws JSONException |
318 | { | |
319 | 0 | return (JSONArray) parse(new XMLTokener(string), true, null, false); |
320 | } | |
321 | ||
322 | /** | |
323 | * Convert a well-formed (but not necessarily valid) XML string into a | |
324 | * JSONArray using the JsonML transform. Each XML tag is represented as a | |
325 | * JSONArray in which the first element is the tag name. If the tag has | |
326 | * attributes, then the second element will be JSONObject containing the | |
327 | * name/value pairs. If the tag contains children, then strings and JSONArrays | |
328 | * will represent the child tags. As opposed to toJSONArray this method does | |
329 | * not attempt to convert any text node or attribute value to any type but | |
330 | * just leaves it as a string. Comments, prologs, DTDs, and | |
331 | * <code><[ [ ]]></code> are ignored. | |
332 | * | |
333 | * @param string | |
334 | * The source string. | |
335 | * @param keepStrings | |
336 | * If true, then values will not be coerced into boolean or numeric | |
337 | * values and will instead be left as strings | |
338 | * @return A JSONArray containing the structured data from the XML string. | |
339 | * @throws JSONException | |
340 | * Thrown on error converting to a JSONArray | |
341 | */ | |
342 | 0 | public static JSONArray toJSONArray(String string, boolean keepStrings) |
343 | throws JSONException | |
344 | { | |
345 | 0 | return (JSONArray) parse(new XMLTokener(string), true, null, |
346 | keepStrings); | |
347 | } | |
348 | ||
349 | /** | |
350 | * Convert a well-formed (but not necessarily valid) XML string into a | |
351 | * JSONArray using the JsonML transform. Each XML tag is represented as a | |
352 | * JSONArray in which the first element is the tag name. If the tag has | |
353 | * attributes, then the second element will be JSONObject containing the | |
354 | * name/value pairs. If the tag contains children, then strings and JSONArrays | |
355 | * will represent the child content and tags. As opposed to toJSONArray this | |
356 | * method does not attempt to convert any text node or attribute value to any | |
357 | * type but just leaves it as a string. Comments, prologs, DTDs, and | |
358 | * <code><[ [ ]]></code> are ignored. | |
359 | * | |
360 | * @param x | |
361 | * An XMLTokener. | |
362 | * @param keepStrings | |
363 | * If true, then values will not be coerced into boolean or numeric | |
364 | * values and will instead be left as strings | |
365 | * @return A JSONArray containing the structured data from the XML string. | |
366 | * @throws JSONException | |
367 | * Thrown on error converting to a JSONArray | |
368 | */ | |
369 | 0 | public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) |
370 | throws JSONException | |
371 | { | |
372 | 0 | return (JSONArray) parse(x, true, null, keepStrings); |
373 | } | |
374 | ||
375 | /** | |
376 | * Convert a well-formed (but not necessarily valid) XML string into a | |
377 | * JSONArray using the JsonML transform. Each XML tag is represented as a | |
378 | * JSONArray in which the first element is the tag name. If the tag has | |
379 | * attributes, then the second element will be JSONObject containing the | |
380 | * name/value pairs. If the tag contains children, then strings and JSONArrays | |
381 | * will represent the child content and tags. Comments, prologs, DTDs, and | |
382 | * <code><[ [ ]]></code> are ignored. | |
383 | * | |
384 | * @param x | |
385 | * An XMLTokener. | |
386 | * @return A JSONArray containing the structured data from the XML string. | |
387 | * @throws JSONException | |
388 | * Thrown on error converting to a JSONArray | |
389 | */ | |
390 | 0 | public static JSONArray toJSONArray(XMLTokener x) throws JSONException |
391 | { | |
392 | 0 | return (JSONArray) parse(x, true, null, false); |
393 | } | |
394 | ||
395 | /** | |
396 | * Convert a well-formed (but not necessarily valid) XML string into a | |
397 | * JSONObject using the JsonML transform. Each XML tag is represented as a | |
398 | * JSONObject with a "tagName" property. If the tag has attributes, then the | |
399 | * attributes will be in the JSONObject as properties. If the tag contains | |
400 | * children, the object will have a "childNodes" property which will be an | |
401 | * array of strings and JsonML JSONObjects. | |
402 | * | |
403 | * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. | |
404 | * | |
405 | * @param string | |
406 | * The XML source text. | |
407 | * @return A JSONObject containing the structured data from the XML string. | |
408 | * @throws JSONException | |
409 | * Thrown on error converting to a JSONObject | |
410 | */ | |
411 | 0 | public static JSONObject toJSONObject(String string) throws JSONException |
412 | { | |
413 | 0 | return (JSONObject) parse(new XMLTokener(string), false, null, false); |
414 | } | |
415 | ||
416 | /** | |
417 | * Convert a well-formed (but not necessarily valid) XML string into a | |
418 | * JSONObject using the JsonML transform. Each XML tag is represented as a | |
419 | * JSONObject with a "tagName" property. If the tag has attributes, then the | |
420 | * attributes will be in the JSONObject as properties. If the tag contains | |
421 | * children, the object will have a "childNodes" property which will be an | |
422 | * array of strings and JsonML JSONObjects. | |
423 | * | |
424 | * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. | |
425 | * | |
426 | * @param string | |
427 | * The XML source text. | |
428 | * @param keepStrings | |
429 | * If true, then values will not be coerced into boolean or numeric | |
430 | * values and will instead be left as strings | |
431 | * @return A JSONObject containing the structured data from the XML string. | |
432 | * @throws JSONException | |
433 | * Thrown on error converting to a JSONObject | |
434 | */ | |
435 | 0 | public static JSONObject toJSONObject(String string, boolean keepStrings) |
436 | throws JSONException | |
437 | { | |
438 | 0 | return (JSONObject) parse(new XMLTokener(string), false, null, |
439 | keepStrings); | |
440 | } | |
441 | ||
442 | /** | |
443 | * Convert a well-formed (but not necessarily valid) XML string into a | |
444 | * JSONObject using the JsonML transform. Each XML tag is represented as a | |
445 | * JSONObject with a "tagName" property. If the tag has attributes, then the | |
446 | * attributes will be in the JSONObject as properties. If the tag contains | |
447 | * children, the object will have a "childNodes" property which will be an | |
448 | * array of strings and JsonML JSONObjects. | |
449 | * | |
450 | * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. | |
451 | * | |
452 | * @param x | |
453 | * An XMLTokener of the XML source text. | |
454 | * @return A JSONObject containing the structured data from the XML string. | |
455 | * @throws JSONException | |
456 | * Thrown on error converting to a JSONObject | |
457 | */ | |
458 | 0 | public static JSONObject toJSONObject(XMLTokener x) throws JSONException |
459 | { | |
460 | 0 | return (JSONObject) parse(x, false, null, false); |
461 | } | |
462 | ||
463 | /** | |
464 | * Convert a well-formed (but not necessarily valid) XML string into a | |
465 | * JSONObject using the JsonML transform. Each XML tag is represented as a | |
466 | * JSONObject with a "tagName" property. If the tag has attributes, then the | |
467 | * attributes will be in the JSONObject as properties. If the tag contains | |
468 | * children, the object will have a "childNodes" property which will be an | |
469 | * array of strings and JsonML JSONObjects. | |
470 | * | |
471 | * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. | |
472 | * | |
473 | * @param x | |
474 | * An XMLTokener of the XML source text. | |
475 | * @param keepStrings | |
476 | * If true, then values will not be coerced into boolean or numeric | |
477 | * values and will instead be left as strings | |
478 | * @return A JSONObject containing the structured data from the XML string. | |
479 | * @throws JSONException | |
480 | * Thrown on error converting to a JSONObject | |
481 | */ | |
482 | 0 | public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) |
483 | throws JSONException | |
484 | { | |
485 | 0 | return (JSONObject) parse(x, false, null, keepStrings); |
486 | } | |
487 | ||
488 | /** | |
489 | * Reverse the JSONML transformation, making an XML text from a JSONArray. | |
490 | * | |
491 | * @param ja | |
492 | * A JSONArray. | |
493 | * @return An XML string. | |
494 | * @throws JSONException | |
495 | * Thrown on error converting to a string | |
496 | */ | |
497 | 0 | public static String toString(JSONArray ja) throws JSONException |
498 | { | |
499 | 0 | int i; |
500 | 0 | JSONObject jo; |
501 | 0 | int length; |
502 | 0 | Object object; |
503 | 0 | StringBuilder sb = new StringBuilder(); |
504 | 0 | String tagName; |
505 | ||
506 | // Emit <tagName | |
507 | ||
508 | 0 | tagName = ja.getString(0); |
509 | 0 | XML.noSpace(tagName); |
510 | 0 | tagName = XML.escape(tagName); |
511 | 0 | sb.append('<'); |
512 | 0 | sb.append(tagName); |
513 | ||
514 | 0 | object = ja.opt(1); |
515 | 0 | if (object instanceof JSONObject) |
516 | { | |
517 | 0 | i = 2; |
518 | 0 | jo = (JSONObject) object; |
519 | ||
520 | // Emit the attributes | |
521 | ||
522 | // Don't use the new entrySet API to maintain Android support | |
523 | 0 | for (final String key : jo.keySet()) |
524 | { | |
525 | 0 | final Object value = jo.opt(key); |
526 | 0 | XML.noSpace(key); |
527 | 0 | if (value != null) |
528 | { | |
529 | 0 | sb.append(' '); |
530 | 0 | sb.append(XML.escape(key)); |
531 | 0 | sb.append('='); |
532 | 0 | sb.append('"'); |
533 | 0 | sb.append(XML.escape(value.toString())); |
534 | 0 | sb.append('"'); |
535 | } | |
536 | } | |
537 | } | |
538 | else | |
539 | { | |
540 | 0 | i = 1; |
541 | } | |
542 | ||
543 | // Emit content in body | |
544 | ||
545 | 0 | length = ja.length(); |
546 | 0 | if (i >= length) |
547 | { | |
548 | 0 | sb.append('/'); |
549 | 0 | sb.append('>'); |
550 | } | |
551 | else | |
552 | { | |
553 | 0 | sb.append('>'); |
554 | 0 | do |
555 | { | |
556 | 0 | object = ja.get(i); |
557 | 0 | i += 1; |
558 | 0 | if (object != null) |
559 | { | |
560 | 0 | if (object instanceof String) |
561 | { | |
562 | 0 | sb.append(XML.escape(object.toString())); |
563 | } | |
564 | 0 | else if (object instanceof JSONObject) |
565 | { | |
566 | 0 | sb.append(toString((JSONObject) object)); |
567 | } | |
568 | 0 | else if (object instanceof JSONArray) |
569 | { | |
570 | 0 | sb.append(toString((JSONArray) object)); |
571 | } | |
572 | else | |
573 | { | |
574 | 0 | sb.append(object.toString()); |
575 | } | |
576 | } | |
577 | 0 | } while (i < length); |
578 | 0 | sb.append('<'); |
579 | 0 | sb.append('/'); |
580 | 0 | sb.append(tagName); |
581 | 0 | sb.append('>'); |
582 | } | |
583 | 0 | return sb.toString(); |
584 | } | |
585 | ||
586 | /** | |
587 | * Reverse the JSONML transformation, making an XML text from a JSONObject. | |
588 | * The JSONObject must contain a "tagName" property. If it has children, then | |
589 | * it must have a "childNodes" property containing an array of objects. The | |
590 | * other properties are attributes with string values. | |
591 | * | |
592 | * @param jo | |
593 | * A JSONObject. | |
594 | * @return An XML string. | |
595 | * @throws JSONException | |
596 | * Thrown on error converting to a string | |
597 | */ | |
598 | 0 | public static String toString(JSONObject jo) throws JSONException |
599 | { | |
600 | 0 | StringBuilder sb = new StringBuilder(); |
601 | 0 | int i; |
602 | 0 | JSONArray ja; |
603 | 0 | int length; |
604 | 0 | Object object; |
605 | 0 | String tagName; |
606 | 0 | Object value; |
607 | ||
608 | // Emit <tagName | |
609 | ||
610 | 0 | tagName = jo.optString("tagName"); |
611 | 0 | if (tagName == null) |
612 | { | |
613 | 0 | return XML.escape(jo.toString()); |
614 | } | |
615 | 0 | XML.noSpace(tagName); |
616 | 0 | tagName = XML.escape(tagName); |
617 | 0 | sb.append('<'); |
618 | 0 | sb.append(tagName); |
619 | ||
620 | // Emit the attributes | |
621 | ||
622 | // Don't use the new entrySet API to maintain Android support | |
623 | 0 | for (final String key : jo.keySet()) |
624 | { | |
625 | 0 | if (!"tagName".equals(key) && !"childNodes".equals(key)) |
626 | { | |
627 | 0 | XML.noSpace(key); |
628 | 0 | value = jo.opt(key); |
629 | 0 | if (value != null) |
630 | { | |
631 | 0 | sb.append(' '); |
632 | 0 | sb.append(XML.escape(key)); |
633 | 0 | sb.append('='); |
634 | 0 | sb.append('"'); |
635 | 0 | sb.append(XML.escape(value.toString())); |
636 | 0 | sb.append('"'); |
637 | } | |
638 | } | |
639 | } | |
640 | ||
641 | // Emit content in body | |
642 | ||
643 | 0 | ja = jo.optJSONArray("childNodes"); |
644 | 0 | if (ja == null) |
645 | { | |
646 | 0 | sb.append('/'); |
647 | 0 | sb.append('>'); |
648 | } | |
649 | else | |
650 | { | |
651 | 0 | sb.append('>'); |
652 | 0 | length = ja.length(); |
653 | 0 | for (i = 0; i < length; i += 1) |
654 | { | |
655 | 0 | object = ja.get(i); |
656 | 0 | if (object != null) |
657 | { | |
658 | 0 | if (object instanceof String) |
659 | { | |
660 | 0 | sb.append(XML.escape(object.toString())); |
661 | } | |
662 | 0 | else if (object instanceof JSONObject) |
663 | { | |
664 | 0 | sb.append(toString((JSONObject) object)); |
665 | } | |
666 | 0 | else if (object instanceof JSONArray) |
667 | { | |
668 | 0 | sb.append(toString((JSONArray) object)); |
669 | } | |
670 | else | |
671 | { | |
672 | 0 | sb.append(object.toString()); |
673 | } | |
674 | } | |
675 | } | |
676 | 0 | sb.append('<'); |
677 | 0 | sb.append('/'); |
678 | 0 | sb.append(tagName); |
679 | 0 | sb.append('>'); |
680 | } | |
681 | 0 | return sb.toString(); |
682 | } | |
683 | } |