@@ -37,6 +37,7 @@ of this software and associated documentation files (the "Software"), to deal
3737 */
3838@ SuppressWarnings ("boxing" )
3939public class XML {
40+
4041 /** The Character '&'. */
4142 public static final Character AMP = '&' ;
4243
@@ -241,7 +242,7 @@ public static void noSpace(String string) throws JSONException {
241242 * @return true if the close tag is processed.
242243 * @throws JSONException
243244 */
244- private static boolean parse (XMLTokener x , JSONObject context , String name , boolean keepStrings )
245+ private static boolean parse (XMLTokener x , JSONObject context , String name , XMLParserConfiguration config )
245246 throws JSONException {
246247 char c ;
247248 int i ;
@@ -278,7 +279,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, bool
278279 if (x .next () == '[' ) {
279280 string = x .nextCDATA ();
280281 if (string .length () > 0 ) {
281- context .accumulate ("content" , string );
282+ context .accumulate (config . cDataTagName , string );
282283 }
283284 return false ;
284285 }
@@ -341,7 +342,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, bool
341342 throw x .syntaxError ("Missing value" );
342343 }
343344 jsonobject .accumulate (string ,
344- keepStrings ? ((String )token ) : stringToValue ((String ) token ));
345+ config . keepStrings ? ((String )token ) : stringToValue ((String ) token ));
345346 token = null ;
346347 } else {
347348 jsonobject .accumulate (string , "" );
@@ -372,19 +373,19 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, bool
372373 } else if (token instanceof String ) {
373374 string = (String ) token ;
374375 if (string .length () > 0 ) {
375- jsonobject .accumulate ("content" ,
376- keepStrings ? string : stringToValue (string ));
376+ jsonobject .accumulate (config . cDataTagName ,
377+ config . keepStrings ? string : stringToValue (string ));
377378 }
378379
379380 } else if (token == LT ) {
380381 // Nested element
381- if (parse (x , jsonobject , tagName ,keepStrings )) {
382+ if (parse (x , jsonobject , tagName , config )) {
382383 if (jsonobject .length () == 0 ) {
383384 context .accumulate (tagName , "" );
384385 } else if (jsonobject .length () == 1
385- && jsonobject .opt ("content" ) != null ) {
386+ && jsonobject .opt (config . cDataTagName ) != null ) {
386387 context .accumulate (tagName ,
387- jsonobject .opt ("content" ));
388+ jsonobject .opt (config . cDataTagName ));
388389 } else {
389390 context .accumulate (tagName , jsonobject );
390391 }
@@ -469,7 +470,7 @@ public static Object stringToValue(String string) {
469470 * @throws JSONException Thrown if there is an errors while parsing the string
470471 */
471472 public static JSONObject toJSONObject (String string ) throws JSONException {
472- return toJSONObject (string , false );
473+ return toJSONObject (string , XMLParserConfiguration . ORIGINAL );
473474 }
474475
475476 /**
@@ -488,7 +489,7 @@ public static JSONObject toJSONObject(String string) throws JSONException {
488489 * @throws JSONException Thrown if there is an errors while parsing the string
489490 */
490491 public static JSONObject toJSONObject (Reader reader ) throws JSONException {
491- return toJSONObject (reader , false );
492+ return toJSONObject (reader , XMLParserConfiguration . ORIGINAL );
492493 }
493494
494495 /**
@@ -512,12 +513,38 @@ public static JSONObject toJSONObject(Reader reader) throws JSONException {
512513 * @throws JSONException Thrown if there is an errors while parsing the string
513514 */
514515 public static JSONObject toJSONObject (Reader reader , boolean keepStrings ) throws JSONException {
516+ if (keepStrings ) {
517+ return toJSONObject (reader , XMLParserConfiguration .KEEP_STRINGS );
518+ }
519+ return toJSONObject (reader , XMLParserConfiguration .ORIGINAL );
520+ }
521+
522+ /**
523+ * Convert a well-formed (but not necessarily valid) XML into a
524+ * JSONObject. Some information may be lost in this transformation because
525+ * JSON is a data format and XML is a document format. XML uses elements,
526+ * attributes, and content text, while JSON uses unordered collections of
527+ * name/value pairs and arrays of values. JSON does not does not like to
528+ * distinguish between elements and attributes. Sequences of similar
529+ * elements are represented as JSONArrays. Content text may be placed in a
530+ * "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
531+ * are ignored.
532+ *
533+ * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
534+ * numbers but will instead be the exact value as seen in the XML document.
535+ *
536+ * @param reader The XML source reader.
537+ * @param config Configuration options for the parser
538+ * @return A JSONObject containing the structured data from the XML string.
539+ * @throws JSONException Thrown if there is an errors while parsing the string
540+ */
541+ public static JSONObject toJSONObject (Reader reader , XMLParserConfiguration config ) throws JSONException {
515542 JSONObject jo = new JSONObject ();
516543 XMLTokener x = new XMLTokener (reader );
517544 while (x .more ()) {
518545 x .skipPast ("<" );
519546 if (x .more ()) {
520- parse (x , jo , null , keepStrings );
547+ parse (x , jo , null , config );
521548 }
522549 }
523550 return jo ;
@@ -548,6 +575,30 @@ public static JSONObject toJSONObject(String string, boolean keepStrings) throws
548575 return toJSONObject (new StringReader (string ), keepStrings );
549576 }
550577
578+ /**
579+ * Convert a well-formed (but not necessarily valid) XML string into a
580+ * JSONObject. Some information may be lost in this transformation because
581+ * JSON is a data format and XML is a document format. XML uses elements,
582+ * attributes, and content text, while JSON uses unordered collections of
583+ * name/value pairs and arrays of values. JSON does not does not like to
584+ * distinguish between elements and attributes. Sequences of similar
585+ * elements are represented as JSONArrays. Content text may be placed in a
586+ * "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
587+ * are ignored.
588+ *
589+ * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
590+ * numbers but will instead be the exact value as seen in the XML document.
591+ *
592+ * @param string
593+ * The source string.
594+ * @param config Configuration options for the parser.
595+ * @return A JSONObject containing the structured data from the XML string.
596+ * @throws JSONException Thrown if there is an errors while parsing the string
597+ */
598+ public static JSONObject toJSONObject (String string , XMLParserConfiguration config ) throws JSONException {
599+ return toJSONObject (new StringReader (string ), config );
600+ }
601+
551602 /**
552603 * Convert a JSONObject into a well-formed, element-normal XML string.
553604 *
@@ -557,7 +608,21 @@ public static JSONObject toJSONObject(String string, boolean keepStrings) throws
557608 * @throws JSONException Thrown if there is an error parsing the string
558609 */
559610 public static String toString (Object object ) throws JSONException {
560- return toString (object , null );
611+ return toString (object , null , XMLParserConfiguration .ORIGINAL );
612+ }
613+
614+ /**
615+ * Convert a JSONObject into a well-formed, element-normal XML string.
616+ *
617+ * @param object
618+ * A JSONObject.
619+ * @param tagName
620+ * The optional name of the enclosing tag.
621+ * @return A string.
622+ * @throws JSONException Thrown if there is an error parsing the string
623+ */
624+ public static String toString (final Object object , final String tagName ) {
625+ return toString (object , tagName , XMLParserConfiguration .ORIGINAL );
561626 }
562627
563628 /**
@@ -567,10 +632,12 @@ public static String toString(Object object) throws JSONException {
567632 * A JSONObject.
568633 * @param tagName
569634 * The optional name of the enclosing tag.
635+ * @param config
636+ * Configuration that can control output to XML.
570637 * @return A string.
571638 * @throws JSONException Thrown if there is an error parsing the string
572639 */
573- public static String toString (final Object object , final String tagName )
640+ public static String toString (final Object object , final String tagName , final XMLParserConfiguration config )
574641 throws JSONException {
575642 StringBuilder sb = new StringBuilder ();
576643 JSONArray ja ;
@@ -598,7 +665,7 @@ public static String toString(final Object object, final String tagName)
598665 }
599666
600667 // Emit content in body
601- if ("content" .equals (key )) {
668+ if (key .equals (config . cDataTagName )) {
602669 if (value instanceof JSONArray ) {
603670 ja = (JSONArray ) value ;
604671 int jaLength = ja .length ();
@@ -626,12 +693,12 @@ public static String toString(final Object object, final String tagName)
626693 sb .append ('<' );
627694 sb .append (key );
628695 sb .append ('>' );
629- sb .append (toString (val ));
696+ sb .append (toString (val , null , config ));
630697 sb .append ("</" );
631698 sb .append (key );
632699 sb .append ('>' );
633700 } else {
634- sb .append (toString (val , key ));
701+ sb .append (toString (val , key , config ));
635702 }
636703 }
637704 } else if ("" .equals (value )) {
@@ -642,7 +709,7 @@ public static String toString(final Object object, final String tagName)
642709 // Emit a new tag <k>
643710
644711 } else {
645- sb .append (toString (value , key ));
712+ sb .append (toString (value , key , config ));
646713 }
647714 }
648715 if (tagName != null ) {
@@ -669,7 +736,7 @@ public static String toString(final Object object, final String tagName)
669736 // XML does not have good support for arrays. If an array
670737 // appears in a place where XML is lacking, synthesize an
671738 // <array> element.
672- sb .append (toString (val , tagName == null ? "array" : tagName ));
739+ sb .append (toString (val , tagName == null ? "array" : tagName , config ));
673740 }
674741 return sb .toString ();
675742 }
0 commit comments