Skip to content

Commit a4f430a

Browse files
authored
Sync with underscore-java
1 parent 8a8f0dd commit a4f430a

File tree

4 files changed

+139
-25
lines changed

4 files changed

+139
-25
lines changed

src/main/java/com/github/underscore/U.java

+15
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public class U<T> extends Underscore<T> {
9595
private static final String SELF_CLOSING = "-self-closing";
9696
private static final String NIL_KEY = "-nil";
9797
private static final String OMIT_XML_DECL = "#omit-xml-declaration";
98+
private static final String YES = "yes";
9899
private static final java.util.regex.Pattern RE_WORDS =
99100
java.util.regex.Pattern.compile(
100101
UPPER
@@ -2701,6 +2702,20 @@ public static String jsonToXml(String json) {
27012702
return jsonToXml(json, Xml.XmlStringBuilder.Step.TWO_SPACES, null, null);
27022703
}
27032704

2705+
@SuppressWarnings("unchecked")
2706+
public static String jsonToXmlMinimum(String json, Xml.XmlStringBuilder.Step identStep) {
2707+
Object object = Json.fromJson(json);
2708+
if (object instanceof Map) {
2709+
((Map<String, Object>) object).put(OMIT_XML_DECL, YES);
2710+
return Xml.toXml(replaceNumberAndBooleanWithString((Map) object), identStep);
2711+
}
2712+
return Xml.toXmlWithoutRoot((List) object, identStep);
2713+
}
2714+
2715+
public static String jsonToXmlMinimum(String json) {
2716+
return jsonToXmlMinimum(json, Xml.XmlStringBuilder.Step.TWO_SPACES);
2717+
}
2718+
27042719
@SuppressWarnings("unchecked")
27052720
public static String xmlToJson(
27062721
String xml, Json.JsonStringBuilder.Step identStep, XmlToJsonMode mode) {

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

+28-23
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ object Xml {
9595
return builder.toString()
9696
}
9797

98+
@JvmStatic
99+
fun toXmlWithoutRoot(collection: Collection<*>, identStep: XmlStringBuilder.Step): String {
100+
val builder = XmlStringBuilderWithoutHeader(identStep, 0)
101+
writeArray(collection, builder, ARRAY_TRUE)
102+
return builder.toString()
103+
}
104+
98105
@JvmOverloads
99106
@JvmStatic
100107
fun toXml(
@@ -486,34 +493,32 @@ object Xml {
486493

487494
@JvmStatic
488495
fun parseAttributes(source: String): Map<String, String> {
489-
val result: MutableMap<String, String> = LinkedHashMap()
496+
val result = LinkedHashMap<String, String>()
490497
val key = StringBuilder()
491498
val value = StringBuilder()
492-
var quoteFound = false
493-
var equalFound = false
494-
var index = 0
495-
while (index < source.length) {
496-
if (source[index] == '=') {
497-
equalFound = !equalFound
498-
index += 1
499-
continue
500-
}
501-
if (source[index] == '"') {
502-
if (quoteFound && equalFound) {
503-
result[key.toString()] = value.toString()
504-
key.setLength(0)
505-
value.setLength(0)
506-
equalFound = false
499+
var inQuotes = false
500+
var expectingValue = false
501+
for (c in source) {
502+
when {
503+
c == '"' -> {
504+
inQuotes = !inQuotes
505+
if (!inQuotes && expectingValue) {
506+
result[key.toString()] = value.toString()
507+
key.clear()
508+
value.clear()
509+
expectingValue = false
510+
}
507511
}
508-
quoteFound = !quoteFound
509-
} else if (quoteFound || SKIPPED_CHARS.contains(source[index])) {
510-
if (quoteFound) {
511-
value.append(source[index])
512+
c == '=' && !inQuotes -> {
513+
expectingValue = true
514+
}
515+
inQuotes -> {
516+
value.append(c)
517+
}
518+
!SKIPPED_CHARS.contains(c) -> {
519+
key.append(c)
512520
}
513-
} else {
514-
key.append(source[index])
515521
}
516-
index += 1
517522
}
518523
return result
519524
}

src/test/java/com/github/underscore/LodashTest.java

+32
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,19 @@ void xmpToJson4() {
10281028
+ "</z:catalog>"));
10291029
}
10301030

1031+
@Test
1032+
void xmpToJson5() {
1033+
assertEquals("{\n"
1034+
+ " \"Comment\": {\n"
1035+
+ " \"-stringValue\": \"============================\",\n"
1036+
+ " \"-self-closing\": \"true\"\n"
1037+
+ " },\n"
1038+
+ " \"#omit-xml-declaration\": \"yes\"\n"
1039+
+ "}",
1040+
U.xmlToJson(
1041+
"<Comment stringValue=\"============================\"/>"));
1042+
}
1043+
10311044
@Test
10321045
void xmlToJsonMinimum() {
10331046
assertEquals(
@@ -1343,6 +1356,25 @@ void jsonToXml() {
13431356
U.jsonToXml("{\"a\" : {\n \"b\" : \"v1\" }, \"c\" : [\"v1\", \"v2\", \"v3\"]}"));
13441357
}
13451358

1359+
@Test
1360+
void jsonToXmlMinimum() {
1361+
assertEquals("<a></a>",
1362+
U.jsonToXmlMinimum("{\n \"a\": {\n }\n}"));
1363+
assertEquals("<a></a>",
1364+
U.jsonToXmlMinimum("{\n \"a\": {\n }\n}", Xml.XmlStringBuilder.Step.TWO_SPACES));
1365+
assertEquals("<root empty-array=\"true\"></root>",
1366+
U.jsonToXmlMinimum("[]"));
1367+
assertEquals("<root>\n"
1368+
+ " <a>\n"
1369+
+ " <b>1</b>\n"
1370+
+ " </a>\n"
1371+
+ " <c>v1</c>\n"
1372+
+ " <c>v2</c>\n"
1373+
+ " <c>v3</c>\n"
1374+
+ "</root>",
1375+
U.jsonToXmlMinimum("{\"a\" : {\n \"b\" : 1 }, \"c\" : [\"v1\", \"v2\", \"v3\"]}"));
1376+
}
1377+
13461378
@Test
13471379
void getTextType() {
13481380
assertEquals(

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

+64-2
Original file line numberDiff line numberDiff line change
@@ -2355,9 +2355,71 @@ void parseAttributes() {
23552355
"{version=1.0}",
23562356
Xml.parseAttributes(" version = \"1.0\" encoding= \"UTF-8 ").toString());
23572357
assertEquals(
2358-
"{}", Xml.parseAttributes(" version = \"1.0 encoding= \"UTF-8\" ").toString());
2358+
"{version=1.0 encoding= }",
2359+
Xml.parseAttributes(" version = \"1.0 encoding= \"UTF-8\" ").toString());
23592360
assertEquals(
2360-
"{}", Xml.parseAttributes(" version = 1.0\" encoding= \"UTF-8\" ").toString());
2361+
"{version1.0= encoding= }",
2362+
Xml.parseAttributes(" version = 1.0\" encoding= \"UTF-8\" ").toString());
2363+
}
2364+
2365+
@Test
2366+
void testSingleAttribute() {
2367+
Map<String, String> result = Xml.parseAttributes("key1=\"value1\"");
2368+
assertEquals(Map.of("key1", "value1"), result);
2369+
}
2370+
2371+
@Test
2372+
void testMultipleAttributes() {
2373+
Map<String, String> result = Xml.parseAttributes("key1=\"value1\" key2=\"value2\"");
2374+
assertEquals(Map.of("key1", "value1", "key2", "value2"), result);
2375+
}
2376+
2377+
@Test
2378+
void testAttributeWithSpaces() {
2379+
Map<String, String> result = Xml.parseAttributes("key1=\"value with spaces\" key2=\"another value\"");
2380+
assertEquals(Map.of("key1", "value with spaces", "key2", "another value"), result);
2381+
}
2382+
2383+
@Test
2384+
void testEmptyValue() {
2385+
Map<String, String> result = Xml.parseAttributes("key1=\"value1\" key2=\"\"");
2386+
assertEquals(Map.of("key1", "value1", "key2", ""), result);
2387+
}
2388+
2389+
@Test
2390+
void testAttributesWithoutSpaceSeparation() {
2391+
Map<String, String> result = Xml.parseAttributes("key1=\"value1\"key2=\"value2\"");
2392+
assertEquals(Map.of("key1", "value1", "key2", "value2"), result);
2393+
}
2394+
2395+
@Test
2396+
void testUnclosedQuotes() {
2397+
Map<String, String> result = Xml.parseAttributes("key1=\"value1 key2=\"value2\"");
2398+
assertEquals(Map.of("key1", "value1 key2="), result);
2399+
}
2400+
2401+
@Test
2402+
void testEqualsSignInValue() {
2403+
Map<String, String> result = Xml.parseAttributes("key1=\"value=1\" key2=\"value=2\"");
2404+
assertEquals(Map.of("key1", "value=1", "key2", "value=2"), result);
2405+
}
2406+
2407+
@Test
2408+
void testTrailingWhitespace() {
2409+
Map<String, String> result = Xml.parseAttributes("key1=\"value1\" key2=\"value2\" ");
2410+
assertEquals(Map.of("key1", "value1", "key2", "value2"), result);
2411+
}
2412+
2413+
@Test
2414+
void testLeadingWhitespace() {
2415+
Map<String, String> result = Xml.parseAttributes(" key1=\"value1\" key2=\"value2\"");
2416+
assertEquals(Map.of("key1", "value1", "key2", "value2"), result);
2417+
}
2418+
2419+
@Test
2420+
void testNoEqualsSign() {
2421+
Map<String, String> result = Xml.parseAttributes("key1\"value1\" key2=\"value2\"");
2422+
assertEquals(Map.of("key1key2", "value1value2"), result);
23612423
}
23622424

23632425
@SuppressWarnings("unchecked")

0 commit comments

Comments
 (0)