@@ -27,7 +27,32 @@ private static Object parse(
27
27
XMLTokener x ,
28
28
boolean arrayForm ,
29
29
JSONArray ja ,
30
- boolean keepStrings
30
+ boolean keepStrings ,
31
+ int currentNestingDepth
32
+ ) throws JSONException {
33
+ return parse (x ,arrayForm , ja ,
34
+ keepStrings ? JSONMLParserConfiguration .KEEP_STRINGS : JSONMLParserConfiguration .ORIGINAL ,
35
+ currentNestingDepth );
36
+ }
37
+
38
+ /**
39
+ * Parse XML values and store them in a JSONArray.
40
+ * @param x The XMLTokener containing the source string.
41
+ * @param arrayForm true if array form, false if object form.
42
+ * @param ja The JSONArray that is containing the current tag or null
43
+ * if we are at the outermost level.
44
+ * @param config The parser configuration:
45
+ * JSONMLParserConfiguration.ORIGINAL is the default behaviour;
46
+ * JSONMLParserConfiguration.KEEP_STRINGS means Don't type-convert text nodes and attribute values.
47
+ * @return A JSONArray if the value is the outermost tag, otherwise null.
48
+ * @throws JSONException if a parsing error occurs
49
+ */
50
+ private static Object parse (
51
+ XMLTokener x ,
52
+ boolean arrayForm ,
53
+ JSONArray ja ,
54
+ JSONMLParserConfiguration config ,
55
+ int currentNestingDepth
31
56
) throws JSONException {
32
57
String attribute ;
33
58
char c ;
@@ -152,7 +177,7 @@ private static Object parse(
152
177
if (!(token instanceof String )) {
153
178
throw x .syntaxError ("Missing value" );
154
179
}
155
- newjo .accumulate (attribute , keepStrings ? ((String )token ) :XML .stringToValue ((String )token ));
180
+ newjo .accumulate (attribute , config . isKeepStrings () ? ((String )token ) :XML .stringToValue ((String )token ));
156
181
token = null ;
157
182
} else {
158
183
newjo .accumulate (attribute , "" );
@@ -181,7 +206,12 @@ private static Object parse(
181
206
if (token != XML .GT ) {
182
207
throw x .syntaxError ("Misshaped tag" );
183
208
}
184
- closeTag = (String )parse (x , arrayForm , newja , keepStrings );
209
+
210
+ if (currentNestingDepth == config .getMaxNestingDepth ()) {
211
+ throw x .syntaxError ("Maximum nesting depth of " + config .getMaxNestingDepth () + " reached" );
212
+ }
213
+
214
+ closeTag = (String )parse (x , arrayForm , newja , config , currentNestingDepth + 1 );
185
215
if (closeTag != null ) {
186
216
if (!closeTag .equals (tagName )) {
187
217
throw x .syntaxError ("Mismatched '" + tagName +
@@ -203,7 +233,7 @@ private static Object parse(
203
233
} else {
204
234
if (ja != null ) {
205
235
ja .put (token instanceof String
206
- ? keepStrings ? XML .unescape ((String )token ) :XML .stringToValue ((String )token )
236
+ ? ( config . isKeepStrings () ? XML .unescape ((String )token ) : XML .stringToValue ((String )token ) )
207
237
: token );
208
238
}
209
239
}
@@ -224,7 +254,7 @@ private static Object parse(
224
254
* @throws JSONException Thrown on error converting to a JSONArray
225
255
*/
226
256
public static JSONArray toJSONArray (String string ) throws JSONException {
227
- return (JSONArray )parse (new XMLTokener (string ), true , null , false );
257
+ return (JSONArray )parse (new XMLTokener (string ), true , null , JSONMLParserConfiguration . ORIGINAL , 0 );
228
258
}
229
259
230
260
@@ -235,8 +265,8 @@ public static JSONArray toJSONArray(String string) throws JSONException {
235
265
* attributes, then the second element will be JSONObject containing the
236
266
* name/value pairs. If the tag contains children, then strings and
237
267
* JSONArrays will represent the child tags.
238
- * As opposed to toJSONArray this method does not attempt to convert
239
- * any text node or attribute value to any type
268
+ * As opposed to toJSONArray this method does not attempt to convert
269
+ * any text node or attribute value to any type
240
270
* but just leaves it as a string.
241
271
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
242
272
* @param string The source string.
@@ -246,7 +276,56 @@ public static JSONArray toJSONArray(String string) throws JSONException {
246
276
* @throws JSONException Thrown on error converting to a JSONArray
247
277
*/
248
278
public static JSONArray toJSONArray (String string , boolean keepStrings ) throws JSONException {
249
- return (JSONArray )parse (new XMLTokener (string ), true , null , keepStrings );
279
+ return (JSONArray )parse (new XMLTokener (string ), true , null , keepStrings , 0 );
280
+ }
281
+
282
+
283
+
284
+ /**
285
+ * Convert a well-formed (but not necessarily valid) XML string into a
286
+ * JSONArray using the JsonML transform. Each XML tag is represented as
287
+ * a JSONArray in which the first element is the tag name. If the tag has
288
+ * attributes, then the second element will be JSONObject containing the
289
+ * name/value pairs. If the tag contains children, then strings and
290
+ * JSONArrays will represent the child tags.
291
+ * As opposed to toJSONArray this method does not attempt to convert
292
+ * any text node or attribute value to any type
293
+ * but just leaves it as a string.
294
+ * Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
295
+ * @param string The source string.
296
+ * @param config The parser configuration:
297
+ * JSONMLParserConfiguration.ORIGINAL is the default behaviour;
298
+ * JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
299
+ * or numeric values and will instead be left as strings
300
+ * @return A JSONArray containing the structured data from the XML string.
301
+ * @throws JSONException Thrown on error converting to a JSONArray
302
+ */
303
+ public static JSONArray toJSONArray (String string , JSONMLParserConfiguration config ) throws JSONException {
304
+ return (JSONArray )parse (new XMLTokener (string ), true , null , config , 0 );
305
+ }
306
+
307
+
308
+ /**
309
+ * Convert a well-formed (but not necessarily valid) XML string into a
310
+ * JSONArray using the JsonML transform. Each XML tag is represented as
311
+ * a JSONArray in which the first element is the tag name. If the tag has
312
+ * attributes, then the second element will be JSONObject containing the
313
+ * name/value pairs. If the tag contains children, then strings and
314
+ * JSONArrays will represent the child content and tags.
315
+ * As opposed to toJSONArray this method does not attempt to convert
316
+ * any text node or attribute value to any type
317
+ * but just leaves it as a string.
318
+ * Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
319
+ * @param x An XMLTokener.
320
+ * @param config The parser configuration:
321
+ * JSONMLParserConfiguration.ORIGINAL is the default behaviour;
322
+ * JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
323
+ * or numeric values and will instead be left as strings
324
+ * @return A JSONArray containing the structured data from the XML string.
325
+ * @throws JSONException Thrown on error converting to a JSONArray
326
+ */
327
+ public static JSONArray toJSONArray (XMLTokener x , JSONMLParserConfiguration config ) throws JSONException {
328
+ return (JSONArray )parse (x , true , null , config , 0 );
250
329
}
251
330
252
331
@@ -257,8 +336,8 @@ public static JSONArray toJSONArray(String string, boolean keepStrings) throws J
257
336
* attributes, then the second element will be JSONObject containing the
258
337
* name/value pairs. If the tag contains children, then strings and
259
338
* JSONArrays will represent the child content and tags.
260
- * As opposed to toJSONArray this method does not attempt to convert
261
- * any text node or attribute value to any type
339
+ * As opposed to toJSONArray this method does not attempt to convert
340
+ * any text node or attribute value to any type
262
341
* but just leaves it as a string.
263
342
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
264
343
* @param x An XMLTokener.
@@ -268,7 +347,7 @@ public static JSONArray toJSONArray(String string, boolean keepStrings) throws J
268
347
* @throws JSONException Thrown on error converting to a JSONArray
269
348
*/
270
349
public static JSONArray toJSONArray (XMLTokener x , boolean keepStrings ) throws JSONException {
271
- return (JSONArray )parse (x , true , null , keepStrings );
350
+ return (JSONArray )parse (x , true , null , keepStrings , 0 );
272
351
}
273
352
274
353
@@ -285,7 +364,7 @@ public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JS
285
364
* @throws JSONException Thrown on error converting to a JSONArray
286
365
*/
287
366
public static JSONArray toJSONArray (XMLTokener x ) throws JSONException {
288
- return (JSONArray )parse (x , true , null , false );
367
+ return (JSONArray )parse (x , true , null , false , 0 );
289
368
}
290
369
291
370
@@ -303,10 +382,10 @@ public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
303
382
* @throws JSONException Thrown on error converting to a JSONObject
304
383
*/
305
384
public static JSONObject toJSONObject (String string ) throws JSONException {
306
- return (JSONObject )parse (new XMLTokener (string ), false , null , false );
385
+ return (JSONObject )parse (new XMLTokener (string ), false , null , false , 0 );
307
386
}
308
-
309
-
387
+
388
+
310
389
/**
311
390
* Convert a well-formed (but not necessarily valid) XML string into a
312
391
* JSONObject using the JsonML transform. Each XML tag is represented as
@@ -323,10 +402,32 @@ public static JSONObject toJSONObject(String string) throws JSONException {
323
402
* @throws JSONException Thrown on error converting to a JSONObject
324
403
*/
325
404
public static JSONObject toJSONObject (String string , boolean keepStrings ) throws JSONException {
326
- return (JSONObject )parse (new XMLTokener (string ), false , null , keepStrings );
405
+ return (JSONObject )parse (new XMLTokener (string ), false , null , keepStrings , 0 );
406
+ }
407
+
408
+
409
+ /**
410
+ * Convert a well-formed (but not necessarily valid) XML string into a
411
+ * JSONObject using the JsonML transform. Each XML tag is represented as
412
+ * a JSONObject with a "tagName" property. If the tag has attributes, then
413
+ * the attributes will be in the JSONObject as properties. If the tag
414
+ * contains children, the object will have a "childNodes" property which
415
+ * will be an array of strings and JsonML JSONObjects.
416
+
417
+ * Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
418
+ * @param string The XML source text.
419
+ * @param config The parser configuration:
420
+ * JSONMLParserConfiguration.ORIGINAL is the default behaviour;
421
+ * JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
422
+ * or numeric values and will instead be left as strings
423
+ * @return A JSONObject containing the structured data from the XML string.
424
+ * @throws JSONException Thrown on error converting to a JSONObject
425
+ */
426
+ public static JSONObject toJSONObject (String string , JSONMLParserConfiguration config ) throws JSONException {
427
+ return (JSONObject )parse (new XMLTokener (string ), false , null , config , 0 );
327
428
}
328
429
329
-
430
+
330
431
/**
331
432
* Convert a well-formed (but not necessarily valid) XML string into a
332
433
* JSONObject using the JsonML transform. Each XML tag is represented as
@@ -341,7 +442,7 @@ public static JSONObject toJSONObject(String string, boolean keepStrings) throws
341
442
* @throws JSONException Thrown on error converting to a JSONObject
342
443
*/
343
444
public static JSONObject toJSONObject (XMLTokener x ) throws JSONException {
344
- return (JSONObject )parse (x , false , null , false );
445
+ return (JSONObject )parse (x , false , null , false , 0 );
345
446
}
346
447
347
448
@@ -361,7 +462,29 @@ public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
361
462
* @throws JSONException Thrown on error converting to a JSONObject
362
463
*/
363
464
public static JSONObject toJSONObject (XMLTokener x , boolean keepStrings ) throws JSONException {
364
- return (JSONObject )parse (x , false , null , keepStrings );
465
+ return (JSONObject )parse (x , false , null , keepStrings , 0 );
466
+ }
467
+
468
+
469
+ /**
470
+ * Convert a well-formed (but not necessarily valid) XML string into a
471
+ * JSONObject using the JsonML transform. Each XML tag is represented as
472
+ * a JSONObject with a "tagName" property. If the tag has attributes, then
473
+ * the attributes will be in the JSONObject as properties. If the tag
474
+ * contains children, the object will have a "childNodes" property which
475
+ * will be an array of strings and JsonML JSONObjects.
476
+
477
+ * Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
478
+ * @param x An XMLTokener of the XML source text.
479
+ * @param config The parser configuration:
480
+ * JSONMLParserConfiguration.ORIGINAL is the default behaviour;
481
+ * JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
482
+ * or numeric values and will instead be left as strings
483
+ * @return A JSONObject containing the structured data from the XML string.
484
+ * @throws JSONException Thrown on error converting to a JSONObject
485
+ */
486
+ public static JSONObject toJSONObject (XMLTokener x , JSONMLParserConfiguration config ) throws JSONException {
487
+ return (JSONObject )parse (x , false , null , config , 0 );
365
488
}
366
489
367
490
@@ -442,6 +565,7 @@ public static String toString(JSONArray ja) throws JSONException {
442
565
return sb .toString ();
443
566
}
444
567
568
+
445
569
/**
446
570
* Reverse the JSONML transformation, making an XML text from a JSONObject.
447
571
* The JSONObject must contain a "tagName" property. If it has children,
0 commit comments