Skip to content

Commit c6ec2f0

Browse files
committed
#748 - close XML tag explicitly for empty tags with configuration.
1 parent 1a2108e commit c6ec2f0

4 files changed

Lines changed: 70 additions & 8 deletions

File tree

src/main/java/org/json/XML.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -877,12 +877,25 @@ private static String toString(final Object object, final String tagName, final
877877
}
878878
}
879879
} else if ("".equals(value)) {
880-
sb.append(indent(indent));
881-
sb.append('<');
882-
sb.append(key);
883-
sb.append("/>");
884-
if(indentFactor > 0){
885-
sb.append("\n");
880+
if (config.isCloseEmptyTag()){
881+
sb.append(indent(indent));
882+
sb.append('<');
883+
sb.append(key);
884+
sb.append(">");
885+
sb.append("</");
886+
sb.append(key);
887+
sb.append(">");
888+
if (indentFactor > 0) {
889+
sb.append("\n");
890+
}
891+
}else {
892+
sb.append(indent(indent));
893+
sb.append('<');
894+
sb.append(key);
895+
sb.append("/>");
896+
if (indentFactor > 0) {
897+
sb.append("\n");
898+
}
886899
}
887900

888901
// Emit a new tag <k>

src/main/java/org/json/XMLParserConfiguration.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ public class XMLParserConfiguration extends ParserConfiguration {
4343
*/
4444
private boolean convertNilAttributeToNull;
4545

46+
/**
47+
* When creating an XML from JSON Object, an empty tag by default will self-close.
48+
* If it has to be closed explicitly, with empty content between start and end tag,
49+
* this flag is to be turned on.
50+
*/
51+
private boolean closeEmptyTag;
52+
4653
/**
4754
* This will allow type conversion for values in XML if xsi:type attribute is defined
4855
*/
@@ -145,12 +152,13 @@ public XMLParserConfiguration (final boolean keepStrings, final String cDataTagN
145152
*/
146153
private XMLParserConfiguration (final boolean keepStrings, final String cDataTagName,
147154
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap, final Set<String> forceList,
148-
final int maxNestingDepth) {
155+
final int maxNestingDepth, final boolean closeEmptyTag) {
149156
super(keepStrings, maxNestingDepth);
150157
this.cDataTagName = cDataTagName;
151158
this.convertNilAttributeToNull = convertNilAttributeToNull;
152159
this.xsiTypeMap = Collections.unmodifiableMap(xsiTypeMap);
153160
this.forceList = Collections.unmodifiableSet(forceList);
161+
this.closeEmptyTag = closeEmptyTag;
154162
}
155163

156164
/**
@@ -169,7 +177,8 @@ protected XMLParserConfiguration clone() {
169177
this.convertNilAttributeToNull,
170178
this.xsiTypeMap,
171179
this.forceList,
172-
this.maxNestingDepth
180+
this.maxNestingDepth,
181+
this.closeEmptyTag
173182
);
174183
}
175184

@@ -303,4 +312,13 @@ public XMLParserConfiguration withForceList(final Set<String> forceList) {
303312
public XMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
304313
return super.withMaxNestingDepth(maxNestingDepth);
305314
}
315+
316+
public XMLParserConfiguration withCloseEmptyTag(boolean closeEmptyTag){
317+
this.closeEmptyTag = closeEmptyTag;
318+
return this;
319+
}
320+
321+
public boolean isCloseEmptyTag() {
322+
return this.closeEmptyTag;
323+
}
306324
}

src/test/java/org/json/junit/XMLConfigurationTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,17 @@ public void shouldHandleNullNodeValue()
557557
assertEquals(actualXML, resultXML);
558558
}
559559

560+
@Test
561+
public void shouldHandleEmptyNodeValue()
562+
{
563+
JSONObject inputJSON = new JSONObject();
564+
inputJSON.put("Emptyness", "");
565+
String expectedXmlWithoutExplicitEndTag = "<Emptyness/>";
566+
String expectedXmlWithExplicitEndTag = "<Emptyness></Emptyness>";
567+
assertEquals(expectedXmlWithoutExplicitEndTag, XML.toString(inputJSON, null, new XMLParserConfiguration().withCloseEmptyTag(false)));
568+
assertEquals(expectedXmlWithExplicitEndTag, XML.toString(inputJSON, null, new XMLParserConfiguration().withCloseEmptyTag(true)));
569+
}
570+
560571
/**
561572
* Investigate exactly how the "content" keyword works
562573
*/

src/test/java/org/json/junit/XMLTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,26 @@ public void testIndentComplicatedJsonObject(){
11771177

11781178

11791179
}
1180+
1181+
@Test
1182+
public void shouldCreateExplicitEndTagWithEmptyValueWhenConfigured(){
1183+
String jsonString = "{outer:{innerOne:\"\", innerTwo:\"two\"}}";
1184+
JSONObject jsonObject = new JSONObject(jsonString);
1185+
String expectedXmlString = "<encloser><outer><innerOne></innerOne><innerTwo>two</innerTwo></outer></encloser>";
1186+
String xmlForm = XML.toString(jsonObject,"encloser", new XMLParserConfiguration().withCloseEmptyTag(true));
1187+
assertEquals(expectedXmlString, xmlForm);
1188+
}
1189+
1190+
@Test
1191+
public void shouldNotCreateExplicitEndTagWithEmptyValueWhenNotConfigured(){
1192+
String jsonString = "{outer:{innerOne:\"\", innerTwo:\"two\"}}";
1193+
JSONObject jsonObject = new JSONObject(jsonString);
1194+
String expectedXmlString = "<encloser><outer><innerOne/><innerTwo>two</innerTwo></outer></encloser>";
1195+
String xmlForm = XML.toString(jsonObject,"encloser", new XMLParserConfiguration().withCloseEmptyTag(false));
1196+
assertEquals(expectedXmlString, xmlForm);
1197+
}
1198+
1199+
11801200
@Test
11811201
public void testIndentSimpleJsonObject(){
11821202
String str = "{ \"employee\": { \n" +

0 commit comments

Comments
 (0)