@@ -27,7 +27,32 @@ private static Object parse(
2727 XMLTokener x ,
2828 boolean arrayForm ,
2929 JSONArray ja ,
30- boolean keepStrings
30+ boolean keepStrings ,
31+ int currentNestingDepth
32+ ) throws JSONException {
33+ return parse (x ,arrayForm , ja ,
34+ keepStrings ? XMLtoJSONMLParserConfiguration .KEEP_STRINGS : XMLtoJSONMLParserConfiguration .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 XML parser configuration:
45+ * XMLtoJSONMLParserConfiguration.ORIGINAL is the default behaviour;
46+ * XMLtoJSONMLParserConfiguration.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+ XMLtoJSONMLParserConfiguration config ,
55+ int currentNestingDepth
3156 ) throws JSONException {
3257 String attribute ;
3358 char c ;
@@ -152,7 +177,7 @@ private static Object parse(
152177 if (!(token instanceof String )) {
153178 throw x .syntaxError ("Missing value" );
154179 }
155- newjo .accumulate (attribute , keepStrings ? ((String )token ) :XML .stringToValue ((String )token ));
180+ newjo .accumulate (attribute , config . isKeepStrings () ? ((String )token ) :XML .stringToValue ((String )token ));
156181 token = null ;
157182 } else {
158183 newjo .accumulate (attribute , "" );
@@ -181,7 +206,12 @@ private static Object parse(
181206 if (token != XML .GT ) {
182207 throw x .syntaxError ("Misshaped tag" );
183208 }
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 );
185215 if (closeTag != null ) {
186216 if (!closeTag .equals (tagName )) {
187217 throw x .syntaxError ("Mismatched '" + tagName +
@@ -203,7 +233,7 @@ private static Object parse(
203233 } else {
204234 if (ja != null ) {
205235 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 ) )
207237 : token );
208238 }
209239 }
@@ -224,7 +254,7 @@ private static Object parse(
224254 * @throws JSONException Thrown on error converting to a JSONArray
225255 */
226256 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 , XMLtoJSONMLParserConfiguration . ORIGINAL , 0 );
228258 }
229259
230260
@@ -235,8 +265,8 @@ public static JSONArray toJSONArray(String string) throws JSONException {
235265 * attributes, then the second element will be JSONObject containing the
236266 * name/value pairs. If the tag contains children, then strings and
237267 * 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
240270 * but just leaves it as a string.
241271 * Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
242272 * @param string The source string.
@@ -246,7 +276,7 @@ public static JSONArray toJSONArray(String string) throws JSONException {
246276 * @throws JSONException Thrown on error converting to a JSONArray
247277 */
248278 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 );
250280 }
251281
252282
@@ -257,8 +287,8 @@ public static JSONArray toJSONArray(String string, boolean keepStrings) throws J
257287 * attributes, then the second element will be JSONObject containing the
258288 * name/value pairs. If the tag contains children, then strings and
259289 * 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
290+ * As opposed to toJSONArray this method does not attempt to convert
291+ * any text node or attribute value to any type
262292 * but just leaves it as a string.
263293 * Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
264294 * @param x An XMLTokener.
@@ -268,7 +298,7 @@ public static JSONArray toJSONArray(String string, boolean keepStrings) throws J
268298 * @throws JSONException Thrown on error converting to a JSONArray
269299 */
270300 public static JSONArray toJSONArray (XMLTokener x , boolean keepStrings ) throws JSONException {
271- return (JSONArray )parse (x , true , null , keepStrings );
301+ return (JSONArray )parse (x , true , null , keepStrings , 0 );
272302 }
273303
274304
@@ -285,7 +315,7 @@ public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JS
285315 * @throws JSONException Thrown on error converting to a JSONArray
286316 */
287317 public static JSONArray toJSONArray (XMLTokener x ) throws JSONException {
288- return (JSONArray )parse (x , true , null , false );
318+ return (JSONArray )parse (x , true , null , false , 0 );
289319 }
290320
291321
@@ -303,10 +333,10 @@ public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
303333 * @throws JSONException Thrown on error converting to a JSONObject
304334 */
305335 public static JSONObject toJSONObject (String string ) throws JSONException {
306- return (JSONObject )parse (new XMLTokener (string ), false , null , false );
336+ return (JSONObject )parse (new XMLTokener (string ), false , null , false , 0 );
307337 }
308-
309-
338+
339+
310340 /**
311341 * Convert a well-formed (but not necessarily valid) XML string into a
312342 * JSONObject using the JsonML transform. Each XML tag is represented as
@@ -323,10 +353,32 @@ public static JSONObject toJSONObject(String string) throws JSONException {
323353 * @throws JSONException Thrown on error converting to a JSONObject
324354 */
325355 public static JSONObject toJSONObject (String string , boolean keepStrings ) throws JSONException {
326- return (JSONObject )parse (new XMLTokener (string ), false , null , keepStrings );
356+ return (JSONObject )parse (new XMLTokener (string ), false , null , keepStrings , 0 );
327357 }
328358
329-
359+
360+ /**
361+ * Convert a well-formed (but not necessarily valid) XML string into a
362+ * JSONObject using the JsonML transform. Each XML tag is represented as
363+ * a JSONObject with a "tagName" property. If the tag has attributes, then
364+ * the attributes will be in the JSONObject as properties. If the tag
365+ * contains children, the object will have a "childNodes" property which
366+ * will be an array of strings and JsonML JSONObjects.
367+
368+ * Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
369+ * @param string The XML source text.
370+ * @param config The XML parser configuration:
371+ * XMLtoJSONMLParserConfiguration.ORIGINAL is the default behaviour;
372+ * XMLtoJSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
373+ * or numeric values and will instead be left as strings
374+ * @return A JSONObject containing the structured data from the XML string.
375+ * @throws JSONException Thrown on error converting to a JSONObject
376+ */
377+ public static JSONObject toJSONObject (String string , XMLtoJSONMLParserConfiguration config ) throws JSONException {
378+ return (JSONObject )parse (new XMLTokener (string ), false , null , config , 0 );
379+ }
380+
381+
330382 /**
331383 * Convert a well-formed (but not necessarily valid) XML string into a
332384 * JSONObject using the JsonML transform. Each XML tag is represented as
@@ -341,7 +393,7 @@ public static JSONObject toJSONObject(String string, boolean keepStrings) throws
341393 * @throws JSONException Thrown on error converting to a JSONObject
342394 */
343395 public static JSONObject toJSONObject (XMLTokener x ) throws JSONException {
344- return (JSONObject )parse (x , false , null , false );
396+ return (JSONObject )parse (x , false , null , false , 0 );
345397 }
346398
347399
@@ -361,7 +413,29 @@ public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
361413 * @throws JSONException Thrown on error converting to a JSONObject
362414 */
363415 public static JSONObject toJSONObject (XMLTokener x , boolean keepStrings ) throws JSONException {
364- return (JSONObject )parse (x , false , null , keepStrings );
416+ return (JSONObject )parse (x , false , null , keepStrings , 0 );
417+ }
418+
419+
420+ /**
421+ * Convert a well-formed (but not necessarily valid) XML string into a
422+ * JSONObject using the JsonML transform. Each XML tag is represented as
423+ * a JSONObject with a "tagName" property. If the tag has attributes, then
424+ * the attributes will be in the JSONObject as properties. If the tag
425+ * contains children, the object will have a "childNodes" property which
426+ * will be an array of strings and JsonML JSONObjects.
427+
428+ * Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
429+ * @param x An XMLTokener of the XML source text.
430+ * @param config The XML parser configuration:
431+ * XMLtoJSONMLParserConfiguration.ORIGINAL is the default behaviour;
432+ * XMLtoJSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
433+ * or numeric values and will instead be left as strings
434+ * @return A JSONObject containing the structured data from the XML string.
435+ * @throws JSONException Thrown on error converting to a JSONObject
436+ */
437+ public static JSONObject toJSONObject (XMLTokener x , XMLtoJSONMLParserConfiguration config ) throws JSONException {
438+ return (JSONObject )parse (x , false , null , config , 0 );
365439 }
366440
367441
@@ -442,6 +516,7 @@ public static String toString(JSONArray ja) throws JSONException {
442516 return sb .toString ();
443517 }
444518
519+
445520 /**
446521 * Reverse the JSONML transformation, making an XML text from a JSONObject.
447522 * The JSONObject must contain a "tagName" property. If it has children,
0 commit comments