Skip to content

Commit acf1bde

Browse files
committed
Sync with underscore-java.
1 parent 63ba3dd commit acf1bde

File tree

2 files changed

+78
-11
lines changed

2 files changed

+78
-11
lines changed

src/main/java/com/github/underscore/lodash/Xml.java

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public final class Xml {
5555
private static final String EMPTY_ARRAY = "-empty-array";
5656
private static final String QUOT = """;
5757
private static final String XML_HEADER = "<?xml ";
58+
private static final String DOCTYPE_TEXT = "!DOCTYPE";
59+
private static final String DOCTYPE_HEADER = "<" + DOCTYPE_TEXT + " ";
5860
private static final java.nio.charset.Charset UTF_8 = java.nio.charset.Charset.forName("UTF-8");
5961
private static final java.util.regex.Pattern ATTRS = java.util.regex.Pattern.compile(
6062
"((?:(?!\\s|=).)*)\\s*?=\\s*?[\"']?((?:(?<=\")(?:(?<=\\\\)\"|[^\"])*|(?<=')"
@@ -610,7 +612,12 @@ public static void writeXml(Object value, String name, XmlStringBuilder builder,
610612
} else if (value instanceof String) {
611613
if (((String) value).isEmpty()) {
612614
builder.append("<" + XmlValue.escapeName(name, namespaces)
613-
+ (addArray ? ARRAY_TRUE : "") + " string=\"true\"/>");
615+
+ (addArray ? ARRAY_TRUE : ""));
616+
if (name.startsWith("?")) {
617+
builder.append("?>");
618+
} else {
619+
builder.append(" string=\"true\"/>");
620+
}
614621
} else {
615622
builder.append("<" + XmlValue.escapeName(name, namespaces)
616623
+ (addArray ? ARRAY_TRUE : "") + (name.startsWith("?") ? " " : ">"));
@@ -898,17 +905,25 @@ public static String toXml(Map map, XmlStringBuilder.Step identStep) {
898905
}
899906

900907
private static void checkLocalMap(final XmlStringBuilder builder, final Map localMap) {
901-
if (localMap == null || localMap.size() != 1
902-
|| XmlValue.getMapKey(localMap).startsWith("-")
903-
|| XmlValue.getMapValue(localMap) instanceof List) {
904-
if ("root".equals(XmlValue.getMapKey(localMap))) {
905-
writeArray((List) XmlValue.getMapValue(localMap), builder);
908+
final Map localMap2;
909+
if (localMap != null && localMap.containsKey(DOCTYPE_TEXT)) {
910+
localMap2 = (Map) U.clone(localMap);
911+
localMap2.remove(DOCTYPE_TEXT);
912+
builder.append(DOCTYPE_HEADER).append(String.valueOf(localMap.get(DOCTYPE_TEXT))).append(">").newLine();
913+
} else {
914+
localMap2 = localMap;
915+
}
916+
if (localMap2 == null || localMap2.size() != 1
917+
|| XmlValue.getMapKey(localMap2).startsWith("-")
918+
|| XmlValue.getMapValue(localMap2) instanceof List) {
919+
if ("root".equals(XmlValue.getMapKey(localMap2))) {
920+
writeArray((List) XmlValue.getMapValue(localMap2), builder);
906921
} else {
907-
XmlObject.writeXml(localMap, getRootName(localMap), builder, false,
922+
XmlObject.writeXml(localMap2, getRootName(localMap2), builder, false,
908923
U.<String>newLinkedHashSet(), false);
909924
}
910925
} else {
911-
XmlObject.writeXml(localMap, null, builder, false, U.<String>newLinkedHashSet(), false);
926+
XmlObject.writeXml(localMap2, null, builder, false, U.<String>newLinkedHashSet(), false);
912927
}
913928
}
914929

@@ -1028,11 +1043,15 @@ private static Object createMap(final org.w3c.dom.Node node,
10281043
value = currentNode.getTextContent();
10291044
}
10301045
if (TEXT.equals(name) && node.getChildNodes().getLength() > 1
1031-
&& String.valueOf(value).trim().isEmpty()
1032-
|| currentNode.getNodeType() == org.w3c.dom.Node.DOCUMENT_TYPE_NODE) {
1046+
&& String.valueOf(value).trim().isEmpty()) {
10331047
continue;
10341048
}
1035-
addNodeValue(map, name, value, elementMapper, nodeMapper, uniqueIds, namespaces, fromType);
1049+
if (currentNode.getNodeType() == org.w3c.dom.Node.DOCUMENT_TYPE_NODE) {
1050+
addNodeValue(map, DOCTYPE_TEXT, getDoctypeValue(source), elementMapper,
1051+
nodeMapper, uniqueIds, namespaces, fromType);
1052+
} else {
1053+
addNodeValue(map, name, value, elementMapper, nodeMapper, uniqueIds, namespaces, fromType);
1054+
}
10361055
}
10371056
return checkNumberAndBoolean(map, node.getNodeName());
10381057
}
@@ -1339,6 +1358,23 @@ private static Map<String, String> getHeaderAttributes(final String xml) {
13391358
return result;
13401359
}
13411360

1361+
protected static String getDoctypeValue(final String xml) {
1362+
int startIndex = xml.indexOf(DOCTYPE_HEADER) + DOCTYPE_HEADER.length();
1363+
char charToFind = '>';
1364+
int endIndexPlus = 0;
1365+
for (int endIndex = startIndex; endIndex < xml.length(); endIndex += 1) {
1366+
if (xml.charAt(endIndex) == '[') {
1367+
charToFind = ']';
1368+
endIndexPlus = 1;
1369+
continue;
1370+
}
1371+
if (xml.charAt(endIndex) == charToFind) {
1372+
return xml.substring(startIndex, endIndex + endIndexPlus);
1373+
}
1374+
}
1375+
return "";
1376+
}
1377+
13421378
private static class MyEntityResolver implements org.xml.sax.EntityResolver {
13431379
public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) {
13441380
return new org.xml.sax.InputSource(new java.io.StringReader(""));

src/test/java/com/github/underscore/lodash/StringTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,6 +1751,7 @@ public void toJsonFromXml15() {
17511751
+ " <phone>(011) 123-4567</phone>\n"
17521752
+ "</address>";
17531753
assertEquals("{\n"
1754+
+ " \"!DOCTYPE\": \"address [\\n]\",\n"
17541755
+ " \"address\": {\n"
17551756
+ " \"name\": \"Tanmay Patil\",\n"
17561757
+ " \"company\": \"TutorialsPoint\",\n"
@@ -2174,13 +2175,22 @@ public void toJsonFromXml24() {
21742175
+ "}";
21752176
assertEquals(json2, U.toJson((Map<String, Object>) U.fromXml(xml2)));
21762177
assertEquals(xml2, U.toXml((Map<String, Object>) U.fromJson(json2)));
2178+
final String xml3 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<a>\n <?b?>\n</a>";
2179+
final String json3 = "{\n"
2180+
+ " \"a\": {\n"
2181+
+ " \"?b\": \"\"\n"
2182+
+ " }\n"
2183+
+ "}";
2184+
assertEquals(json3, U.toJson((Map<String, Object>) U.fromXml(xml3)));
2185+
assertEquals(xml3, U.toXml((Map<String, Object>) U.fromJson(json3)));
21772186
}
21782187

21792188
@SuppressWarnings("unchecked")
21802189
@Test
21812190
public void toJsonFromXml25() {
21822191
final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE address SYSTEM \"address.dtd\"><a></a>";
21832192
final String json = "{\n"
2193+
+ " \"!DOCTYPE\": \"address SYSTEM \\\"address.dtd\\\"\",\n"
21842194
+ " \"a\": {\n"
21852195
+ " }\n"
21862196
+ "}";
@@ -2231,6 +2241,27 @@ public void toJsonFromXml27() {
22312241
assertEquals(xml, U.toXml((Map<String, Object>) U.fromJson(json)));
22322242
}
22332243

2244+
@SuppressWarnings("unchecked")
2245+
@Test
2246+
public void toJsonFromXml28() {
2247+
final String xml = "<!DOCTYPE module PUBLIC\n"
2248+
+ "\"-//Puppy Crawl//DTD Check Configuration 1.3//EN\"\n"
2249+
+ "\"http://www.puppycrawl.com/dtds/configuration_1_3.dtd\">\n"
2250+
+ "<module name=\"Checker\"/>";
2251+
final String json = "{\n"
2252+
+ " \"!DOCTYPE\": \"module PUBLIC\\n\\\"-//Puppy Crawl//DTD Check Configuration 1.3//EN\\\"\\n"
2253+
+ "\\\"http://www.puppycrawl.com/dtds/configuration_1_3.dtd\\\"\",\n"
2254+
+ " \"module\": {\n"
2255+
+ " \"-name\": \"Checker\",\n"
2256+
+ " \"-self-closing\": \"true\"\n"
2257+
+ " },\n"
2258+
+ " \"#omit-xml-declaration\": \"yes\"\n"
2259+
+ "}";
2260+
assertEquals("", Xml.getDoctypeValue("<!DOCTYPE module PUBLIC"));
2261+
assertEquals(json, U.toJson((Map<String, Object>) U.fromXml(xml)));
2262+
assertEquals(xml, U.toXml((Map<String, Object>) U.fromJson(json)));
2263+
}
2264+
22342265
@SuppressWarnings("unchecked")
22352266
@Test
22362267
public void toXmlFromJson() {

0 commit comments

Comments
 (0)