Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close XML tag explicitly for empty tags with configuration. #820

Merged
merged 4 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 19 additions & 6 deletions src/main/java/org/json/XML.java
Original file line number Diff line number Diff line change
Expand Up @@ -877,12 +877,25 @@ private static String toString(final Object object, final String tagName, final
}
}
} else if ("".equals(value)) {
sb.append(indent(indent));
sb.append('<');
sb.append(key);
sb.append("/>");
if(indentFactor > 0){
sb.append("\n");
if (config.isCloseEmptyTag()){
sb.append(indent(indent));
sb.append('<');
sb.append(key);
sb.append(">");
sb.append("</");
sb.append(key);
sb.append(">");
if (indentFactor > 0) {
sb.append("\n");
}
}else {
sb.append(indent(indent));
sb.append('<');
sb.append(key);
sb.append("/>");
if (indentFactor > 0) {
sb.append("\n");
}
}

// Emit a new tag <k>
Expand Down
29 changes: 27 additions & 2 deletions src/main/java/org/json/XMLParserConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ public class XMLParserConfiguration extends ParserConfiguration {
*/
private boolean convertNilAttributeToNull;

/**
* When creating an XML from JSON Object, an empty tag by default will self-close.
* If it has to be closed explicitly, with empty content between start and end tag,
* this flag is to be turned on.
*/
private boolean closeEmptyTag;

/**
* This will allow type conversion for values in XML if xsi:type attribute is defined
*/
Expand Down Expand Up @@ -142,15 +149,17 @@ public XMLParserConfiguration (final boolean keepStrings, final String cDataTagN
* xsi:type="integer" as integer, xsi:type="string" as string
* @param forceList <code>new HashSet<String>()</code> to parse the provided tags' values as arrays
* @param maxNestingDepth <code>int</code> to limit the nesting depth
* @param closeEmptyTag <code>boolean</code> to turn on explicit end tag for tag with empty value
*/
private XMLParserConfiguration (final boolean keepStrings, final String cDataTagName,
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap, final Set<String> forceList,
final int maxNestingDepth) {
final int maxNestingDepth, final boolean closeEmptyTag) {
super(keepStrings, maxNestingDepth);
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = convertNilAttributeToNull;
this.xsiTypeMap = Collections.unmodifiableMap(xsiTypeMap);
this.forceList = Collections.unmodifiableSet(forceList);
this.closeEmptyTag = closeEmptyTag;
}

/**
Expand All @@ -169,7 +178,8 @@ protected XMLParserConfiguration clone() {
this.convertNilAttributeToNull,
this.xsiTypeMap,
this.forceList,
this.maxNestingDepth
this.maxNestingDepth,
this.closeEmptyTag
);
}

Expand Down Expand Up @@ -303,4 +313,19 @@ public XMLParserConfiguration withForceList(final Set<String> forceList) {
public XMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
return super.withMaxNestingDepth(maxNestingDepth);
}

/**
* To enable explicit end tag with empty value.
* @param closeEmptyTag
* @return same instance of configuration with empty tag config updated
*/
public XMLParserConfiguration withCloseEmptyTag(boolean closeEmptyTag){
XMLParserConfiguration clonedConfiguration = this.clone();
clonedConfiguration.closeEmptyTag = closeEmptyTag;
return clonedConfiguration;
}

public boolean isCloseEmptyTag() {
return this.closeEmptyTag;
}
}
38 changes: 33 additions & 5 deletions src/test/java/org/json/junit/XMLConfigurationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@
Public Domain.
*/

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
Expand All @@ -27,6 +22,8 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import static org.junit.Assert.*;


/**
* Tests for JSON-Java XML.java with XMLParserConfiguration.java
Expand Down Expand Up @@ -557,6 +554,37 @@ public void shouldHandleNullNodeValue()
assertEquals(actualXML, resultXML);
}

@Test
public void shouldHandleEmptyNodeValue()
{
JSONObject inputJSON = new JSONObject();
inputJSON.put("Emptyness", "");
String expectedXmlWithoutExplicitEndTag = "<Emptyness/>";
String expectedXmlWithExplicitEndTag = "<Emptyness></Emptyness>";
assertEquals(expectedXmlWithoutExplicitEndTag, XML.toString(inputJSON, null,
new XMLParserConfiguration().withCloseEmptyTag(false)));
assertEquals(expectedXmlWithExplicitEndTag, XML.toString(inputJSON, null,
new XMLParserConfiguration().withCloseEmptyTag(true)));
}

@Test
public void shouldKeepConfigurationIntactAndUpdateCloseEmptyTagChoice()
{
XMLParserConfiguration keepStrings = XMLParserConfiguration.KEEP_STRINGS;
XMLParserConfiguration keepStringsAndCloseEmptyTag = keepStrings.withCloseEmptyTag(true);
XMLParserConfiguration keepDigits = keepStringsAndCloseEmptyTag.withKeepStrings(false);
XMLParserConfiguration keepDigitsAndNoCloseEmptyTag = keepDigits.withCloseEmptyTag(false);
assertTrue(keepStrings.isKeepStrings());
assertFalse(keepStrings.isCloseEmptyTag());
assertTrue(keepStringsAndCloseEmptyTag.isKeepStrings());
assertTrue(keepStringsAndCloseEmptyTag.isCloseEmptyTag());
assertFalse(keepDigits.isKeepStrings());
assertTrue(keepDigits.isCloseEmptyTag());
assertFalse(keepDigitsAndNoCloseEmptyTag.isKeepStrings());
assertFalse(keepDigitsAndNoCloseEmptyTag.isCloseEmptyTag());

}

/**
* Investigate exactly how the "content" keyword works
*/
Expand Down
20 changes: 20 additions & 0 deletions src/test/java/org/json/junit/XMLTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,26 @@ public void testIndentComplicatedJsonObject(){


}

@Test
public void shouldCreateExplicitEndTagWithEmptyValueWhenConfigured(){
String jsonString = "{outer:{innerOne:\"\", innerTwo:\"two\"}}";
JSONObject jsonObject = new JSONObject(jsonString);
String expectedXmlString = "<encloser><outer><innerOne></innerOne><innerTwo>two</innerTwo></outer></encloser>";
String xmlForm = XML.toString(jsonObject,"encloser", new XMLParserConfiguration().withCloseEmptyTag(true));
assertEquals(expectedXmlString, xmlForm);
}

@Test
public void shouldNotCreateExplicitEndTagWithEmptyValueWhenNotConfigured(){
String jsonString = "{outer:{innerOne:\"\", innerTwo:\"two\"}}";
JSONObject jsonObject = new JSONObject(jsonString);
String expectedXmlString = "<encloser><outer><innerOne/><innerTwo>two</innerTwo></outer></encloser>";
String xmlForm = XML.toString(jsonObject,"encloser", new XMLParserConfiguration().withCloseEmptyTag(false));
assertEquals(expectedXmlString, xmlForm);
}


@Test
public void testIndentSimpleJsonObject(){
String str = "{ \"employee\": { \n" +
Expand Down