Skip to content

Commit c896137

Browse files
authored
XML attribute parser has been enhanced
1 parent af39675 commit c896137

File tree

2 files changed

+62
-23
lines changed

2 files changed

+62
-23
lines changed

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

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,7 @@
4343
"java:S1119",
4444
"java:S3740",
4545
"java:S3776",
46-
"java:S4276",
47-
"java:S5843",
48-
"java:S5852",
49-
"java:S5998",
50-
"java:S6019",
51-
"java:S6035",
52-
"java:S6395"
46+
"java:S4276"
5347
})
5448
public final class Xml {
5549
private Xml() {}
@@ -84,10 +78,6 @@ private Xml() {}
8478
private static final String DOCTYPE_TEXT = "!DOCTYPE";
8579
private static final String ROOT = "root";
8680
private static final String DOCTYPE_HEADER = "<" + DOCTYPE_TEXT + " ";
87-
private static final java.util.regex.Pattern ATTRS =
88-
java.util.regex.Pattern.compile(
89-
"((?:(?!\\s|=).)*)\\s*?=\\s*?[\"']?((?:(?<=\")(?:(?<=\\\\)\"|[^\"])*|(?<=')"
90-
+ "(?:(?<=\\\\)'|[^'])*)|(?:(?!\"|')(?:(?!\\/>|>|\\s).)+))");
9181
private static final Map<String, String> XML_UNESCAPE = new HashMap<>();
9282
private static final org.w3c.dom.Document DOCUMENT = Document.createDocument();
9383

@@ -1490,19 +1480,18 @@ private static Object addElement(
14901480
final FromType fromType) {
14911481
final Map<String, Object> attrMapLocal = new LinkedHashMap<>();
14921482
if (currentNode.getAttributes().getLength() > 0) {
1493-
final java.util.regex.Matcher matcher =
1494-
ATTRS.matcher(getAttributes(sourceIndex[0], source));
1495-
while (matcher.find()) {
1496-
if (matcher.group(1).startsWith("xmlns:")) {
1497-
namespaces.add(matcher.group(1).substring(6));
1483+
final Map<String, String> attributes =
1484+
parseAttributes(getAttributes(sourceIndex[0], source));
1485+
for (Map.Entry<String, String> attribute : attributes.entrySet()) {
1486+
if (attribute.getKey().startsWith("xmlns:")) {
1487+
namespaces.add(attribute.getKey().substring(6));
14981488
}
14991489
}
1500-
matcher.reset();
1501-
while (matcher.find()) {
1490+
for (Map.Entry<String, String> attribute : attributes.entrySet()) {
15021491
addNodeValue(
15031492
attrMapLocal,
1504-
'-' + matcher.group(1),
1505-
matcher.group(2),
1493+
'-' + attribute.getKey(),
1494+
attribute.getValue(),
15061495
elementMapper,
15071496
nodeMapper,
15081497
uniqueIds,
@@ -1531,6 +1520,36 @@ private static Object addElement(
15311520
fromType);
15321521
}
15331522

1523+
static Map<String, String> parseAttributes(final String source) {
1524+
final Map<String, String> result = new LinkedHashMap<>();
1525+
final StringBuilder key = new StringBuilder();
1526+
final StringBuilder value = new StringBuilder();
1527+
boolean quoteFound = false;
1528+
boolean equalFound = false;
1529+
for (int index = 0; index < source.length(); index += 1) {
1530+
if (source.charAt(index) == '=') {
1531+
equalFound = !equalFound;
1532+
continue;
1533+
}
1534+
if (source.charAt(index) == '"') {
1535+
if (quoteFound && equalFound) {
1536+
result.put(key.toString(), value.toString());
1537+
key.setLength(0);
1538+
value.setLength(0);
1539+
equalFound = false;
1540+
}
1541+
quoteFound = !quoteFound;
1542+
} else if (quoteFound || source.charAt(index) == ' ') {
1543+
if (quoteFound) {
1544+
value.append(source.charAt(index));
1545+
}
1546+
} else {
1547+
key.append(source.charAt(index));
1548+
}
1549+
}
1550+
return result;
1551+
}
1552+
15341553
static String getAttributes(final int sourceIndex, final String source) {
15351554
boolean scanQuote = false;
15361555
for (int index = sourceIndex; index < source.length(); index += 1) {
@@ -1745,9 +1764,9 @@ private static Map<String, String> getHeaderAttributes(final String xml) {
17451764
xml.substring(
17461765
XML_HEADER.length(),
17471766
Math.max(XML_HEADER.length(), xml.indexOf("?>", XML_HEADER.length())));
1748-
final java.util.regex.Matcher matcher = ATTRS.matcher(xmlLocal);
1749-
while (matcher.find()) {
1750-
result.put(matcher.group(1), matcher.group(2));
1767+
final Map<String, String> attributes = parseAttributes(xmlLocal);
1768+
for (Map.Entry<String, String> attribute : attributes.entrySet()) {
1769+
result.put(attribute.getKey(), attribute.getValue());
17511770
}
17521771
}
17531772
return result;

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2343,6 +2343,26 @@ void toJsonFromXml22() {
23432343
assertEquals("", Xml.getAttributes(0, ""));
23442344
}
23452345

2346+
@Test
2347+
void parseAttributes() {
2348+
assertEquals(
2349+
"{version=1.0, encoding=UTF-8}",
2350+
Xml.parseAttributes("version=\"1.0\" encoding=\"UTF-8\"").toString());
2351+
assertEquals(
2352+
"{version=1.0, encoding=UTF-8}",
2353+
Xml.parseAttributes(" version = \"1.0\" encoding= \"UTF-8\" ").toString());
2354+
assertEquals(
2355+
"{version= 1.0, encoding=UTF-8 }",
2356+
Xml.parseAttributes(" version = \" 1.0\" encoding= \"UTF-8 \" ").toString());
2357+
assertEquals(
2358+
"{version=1.0}",
2359+
Xml.parseAttributes(" version = \"1.0\" encoding= \"UTF-8 ").toString());
2360+
assertEquals(
2361+
"{}", Xml.parseAttributes(" version = \"1.0 encoding= \"UTF-8\" ").toString());
2362+
assertEquals(
2363+
"{}", Xml.parseAttributes(" version = 1.0\" encoding= \"UTF-8\" ").toString());
2364+
}
2365+
23462366
@SuppressWarnings("unchecked")
23472367
@Test
23482368
void toJsonFromXml23() {

0 commit comments

Comments
 (0)