diff --git a/src/main/java/org/json/XML.java b/src/main/java/org/json/XML.java
index 69782cb..28a292f 100644
--- a/src/main/java/org/json/XML.java
+++ b/src/main/java/org/json/XML.java
@@ -752,6 +752,11 @@ public class XML {
*/
public static String toString(final Object object, final String tagName, final XMLParserConfiguration config)
throws JSONException {
+ return toString(object, tagName, config, 0, 0);
+ }
+
+ private static String toString(final Object object, final String tagName, final XMLParserConfiguration config, int indentFactor, int indent)
+ throws JSONException {
StringBuilder sb = new StringBuilder();
JSONArray ja;
JSONObject jo;
@@ -761,9 +766,14 @@ public class XML {
// Emit
if (tagName != null) {
+ sb.append(indent(indent));
sb.append('<');
sb.append(tagName);
sb.append('>');
+ if(indentFactor > 0){
+ sb.append("\n");
+ indent += indentFactor;
+ }
}
// Loop thru the keys.
@@ -806,31 +816,39 @@ public class XML {
sb.append('<');
sb.append(key);
sb.append('>');
- sb.append(toString(val, null, config));
+ sb.append(toString(val, null, config, indentFactor, indent));
sb.append("");
sb.append(key);
sb.append('>');
} else {
- sb.append(toString(val, key, config));
+ sb.append(toString(val, key, config, indentFactor, indent));
}
}
} else if ("".equals(value)) {
+ sb.append(indent(indent));
sb.append('<');
sb.append(key);
sb.append("/>");
+ if(indentFactor > 0){
+ sb.append("\n");
+ }
// Emit a new tag
} else {
- sb.append(toString(value, key, config));
+ sb.append(toString(value, key, config, indentFactor, indent));
}
}
if (tagName != null) {
// Emit the close tag
+ sb.append(indent(indent - indentFactor));
sb.append("");
sb.append(tagName);
sb.append('>');
+ if(indentFactor > 0){
+ sb.append("\n");
+ }
}
return sb.toString();
@@ -849,15 +867,78 @@ public class XML {
// XML does not have good support for arrays. If an array
// appears in a place where XML is lacking, synthesize an
// element.
- sb.append(toString(val, tagName == null ? "array" : tagName, config));
+ sb.append(toString(val, tagName == null ? "array" : tagName, config, indentFactor, indent));
}
return sb.toString();
}
- string = (object == null) ? "null" : escape(object.toString());
- return (tagName == null) ? "\"" + string + "\""
- : (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName
- + ">" + string + "" + tagName + ">";
+ string = (object == null) ? "null" : escape(object.toString());
+
+ if(tagName == null){
+ return indent(indent) + "\"" + string + "\"" + ((indentFactor > 0) ? "\n" : "");
+ } else if(string.length() == 0){
+ return indent(indent) + "<" + tagName + "/>" + ((indentFactor > 0) ? "\n" : "");
+ } else {
+ return indent(indent) + "<" + tagName
+ + ">" + string + "" + tagName + ">" + ((indentFactor > 0) ? "\n" : "");
+ }
+ }
+
+ /**
+ * Convert a JSONObject into a well-formed, pretty printed element-normal XML string.
+ *
+ * @param object
+ * A JSONObject.
+ * @param indentFactor
+ * The number of spaces to add to each level of indentation.
+ * @return A string.
+ * @throws JSONException Thrown if there is an error parsing the string
+ */
+ public static String toString(Object object, int indentFactor){
+ return toString(object, null, XMLParserConfiguration.ORIGINAL, indentFactor);
+ }
+
+ /**
+ * Convert a JSONObject into a well-formed, pretty printed element-normal XML string.
+ *
+ * @param object
+ * A JSONObject.
+ * @param tagName
+ * The optional name of the enclosing tag.
+ * @param indentFactor
+ * The number of spaces to add to each level of indentation.
+ * @return A string.
+ * @throws JSONException Thrown if there is an error parsing the string
+ */
+ public static String toString(final Object object, final String tagName, int indentFactor) {
+ return toString(object, tagName, XMLParserConfiguration.ORIGINAL, indentFactor);
+ }
+
+ /**
+ * Convert a JSONObject into a well-formed, pretty printed element-normal XML string.
+ *
+ * @param object
+ * A JSONObject.
+ * @param tagName
+ * The optional name of the enclosing tag.
+ * @param config
+ * Configuration that can control output to XML.
+ * @param indentFactor
+ * The number of spaces to add to each level of indentation.
+ * @return A string.
+ * @throws JSONException Thrown if there is an error parsing the string
+ */
+ public static String toString(final Object object, final String tagName, final XMLParserConfiguration config, int indentFactor)
+ throws JSONException {
+ return toString(object, tagName, config, indentFactor, 0);
+ }
+
+ private static final String indent(int indent) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < indent; i++) {
+ sb.append(' ');
+ }
+ return sb.toString();
}
}
diff --git a/src/test/java/org/json/junit/XMLTest.java b/src/test/java/org/json/junit/XMLTest.java
index 906924d..9ba2279 100644
--- a/src/test/java/org/json/junit/XMLTest.java
+++ b/src/test/java/org/json/junit/XMLTest.java
@@ -1049,4 +1049,82 @@ public class XMLTest {
fail("Expected to be unable to modify the config");
} catch (Exception ignored) { }
}
+
+ @Test
+ public void testXmlToStringWithIndent(){
+ String str = "{\n" +
+ " \"success\": true,\n" +
+ " \"error\": null,\n" +
+ " \"response\": [\n" +
+ " {\n" +
+ " \"timestamp\": 1664917200,\n" +
+ " \"dateTimeISO\": \"2022-10-05T00:00:00+03:00\",\n" +
+ " \"loc\": {\n" +
+ " \"lat\": 39.91987,\n" +
+ " \"long\": 32.85427\n" +
+ " },\n" +
+ " \"place\": {\n" +
+ " \"name\": \"ankara\",\n" +
+ " \"state\": \"an\",\n" +
+ " \"country\": \"tr\"\n" +
+ " },\n" +
+ " \"profile\": {\n" +
+ " \"tz\": \"Europe/Istanbul\"\n" +
+ " },\n" +
+ " \"sun\": {\n" +
+ " \"rise\": 1664941721,\n" +
+ " \"riseISO\": \"2022-10-05T06:48:41+03:00\",\n" +
+ " \"set\": 1664983521,\n" +
+ " \"setISO\": \"2022-10-05T18:25:21+03:00\",\n" +
+ " \"transit\": 1664962621,\n" +
+ " \"transitISO\": \"2022-10-05T12:37:01+03:00\",\n" +
+ " \"midnightSun\": false,\n" +
+ " \"polarNight\": false,\n" +
+ " \"twilight\": {\n" +
+ " \"civilBegin\": 1664940106,\n" +
+ " \"civilBeginISO\": \"2022-10-05T06:21:46+03:00\",\n" +
+ " \"civilEnd\": 1664985136,\n" +
+ " \"civilEndISO\": \"2022-10-05T18:52:16+03:00\",\n" +
+ " \"nauticalBegin\": 1664938227,\n" +
+ " \"nauticalBeginISO\": \"2022-10-05T05:50:27+03:00\",\n" +
+ " \"nauticalEnd\": 1664987015,\n" +
+ " \"nauticalEndISO\": \"2022-10-05T19:23:35+03:00\",\n" +
+ " \"astronomicalBegin\": 1664936337,\n" +
+ " \"astronomicalBeginISO\": \"2022-10-05T05:18:57+03:00\",\n" +
+ " \"astronomicalEnd\": 1664988905,\n" +
+ " \"astronomicalEndISO\": \"2022-10-05T19:55:05+03:00\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"moon\": {\n" +
+ " \"rise\": 1664976480,\n" +
+ " \"riseISO\": \"2022-10-05T16:28:00+03:00\",\n" +
+ " \"set\": 1664921520,\n" +
+ " \"setISO\": \"2022-10-05T01:12:00+03:00\",\n" +
+ " \"transit\": 1664994240,\n" +
+ " \"transitISO\": \"2022-10-05T21:24:00+03:00\",\n" +
+ " \"underfoot\": 1664949360,\n" +
+ " \"underfootISO\": \"2022-10-05T08:56:00+03:00\",\n" +
+ " \"phase\": {\n" +
+ " \"phase\": 0.3186,\n" +
+ " \"name\": \"waxing gibbous\",\n" +
+ " \"illum\": 71,\n" +
+ " \"age\": 9.41,\n" +
+ " \"angle\": 0.55\n" +
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ " ]\n" +
+ "}" ;
+ JSONObject jsonObject = new JSONObject(str);
+ String xmlString = XML.toString(jsonObject, "Outer", 1);
+ System.out.println(xmlString);
+ System.out.println(XML.toIndentedXmlString(xmlString, 2, true));
+
+
+ }
+
+
}
+
+
+