Skip to content

Commit 61f1179

Browse files
committed
🎨 XmlUtils工具类优化,支持变态微信消息
1 parent 2c27f8b commit 61f1179

File tree

2 files changed

+81
-28
lines changed

2 files changed

+81
-28
lines changed

weixin-java-common/src/main/java/me/chanjar/weixin/common/util/XmlUtils.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.google.common.collect.Lists;
44
import com.google.common.collect.Maps;
55
import com.google.common.collect.Sets;
6-
import me.chanjar.weixin.common.error.WxErrorException;
76
import me.chanjar.weixin.common.error.WxRuntimeException;
87
import org.dom4j.*;
98
import org.dom4j.io.SAXReader;
@@ -15,6 +14,7 @@
1514
import java.util.List;
1615
import java.util.Map;
1716
import java.util.Set;
17+
import java.util.stream.Collectors;
1818

1919
/**
2020
* <pre>
@@ -50,19 +50,20 @@ public static Map<String, Object> xml2Map(String xmlString) {
5050

5151
private static Object element2MapOrString(Element element) {
5252

53-
final List<Node> content = element.content();
54-
final Set<String> names = names(content);
53+
final List<Node> nodes = element.content();
54+
final List<String> names = names(nodes);
5555

5656
// 判断节点下有无非文本节点(非Text和CDATA),如无,直接取Text文本内容
5757
if (names.size() < 1) {
5858
return element.getText();
5959
}
6060

6161
Map<String, Object> result = Maps.newHashMap();
62-
if (names.size() == 1) {
62+
Set<String> distinctNames = Sets.newHashSet(names);
63+
if (distinctNames.size() == 1) {
6364
// 说明是个列表,各个子对象是相同的name
6465
List<Object> list = Lists.newArrayList();
65-
for (Node node : content) {
66+
for (Node node : nodes) {
6667
if (node instanceof DefaultText) {
6768
continue;
6869
}
@@ -73,8 +74,8 @@ private static Object element2MapOrString(Element element) {
7374
}
7475

7576
result.put(names.iterator().next(), list);
76-
} else {
77-
for (Node node : content) {
77+
} else if (distinctNames.size() == names.size()) {
78+
for (Node node : nodes) {
7879
if (node instanceof DefaultText) {
7980
continue;
8081
}
@@ -83,13 +84,38 @@ private static Object element2MapOrString(Element element) {
8384
result.put(node.getName(), element2MapOrString((Element) node));
8485
}
8586
}
87+
} else {
88+
// 说明有重复name,但不是全部都相同
89+
Map<String, Long> namesCountMap = names.stream().collect(Collectors.groupingBy(a -> a, Collectors.counting()));
90+
for (Node node : nodes) {
91+
if (node instanceof DefaultText) {
92+
continue;
93+
}
94+
95+
if (node instanceof Element) {
96+
String nodeName = node.getName();
97+
if (namesCountMap.get(nodeName) == 1) {
98+
result.put(nodeName, element2MapOrString((Element) node));
99+
} else {
100+
List<Object> values;
101+
if (result.containsKey(nodeName)) {
102+
values = (List<Object>) result.get(nodeName);
103+
} else {
104+
values = Lists.newArrayList();
105+
result.put(nodeName, values);
106+
}
107+
108+
values.add(element2MapOrString((Element) node));
109+
}
110+
}
111+
}
86112
}
87113

88114
return result;
89115
}
90116

91-
private static Set<String> names(List<Node> nodes) {
92-
Set<String> names = Sets.newHashSet();
117+
private static List<String> names(List<Node> nodes) {
118+
List<String> names = Lists.newArrayList();
93119
for (Node node : nodes) {
94120
// 如果节点类型是Text或CDATA跳过
95121
if (node instanceof DefaultText || node instanceof CDATA) {

weixin-java-common/src/test/java/me/chanjar/weixin/common/util/XmlUtilsTest.java

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,54 @@ public void testXml2Map() {
6363
assertThat(map).isNotNull();
6464
final Map<String, Object> copyrightCheckResult = (Map<String, Object>) map.get("CopyrightCheckResult");
6565
List<Map<String, Object>> resultList = (List<Map<String, Object>>) ((Map<String, Object>) copyrightCheckResult.get("ResultList")).get("item");
66-
assertThat(copyrightCheckResult).isNotNull();
6766

68-
assertThat(copyrightCheckResult.get("Count")).isEqualTo("2");
69-
assertThat(copyrightCheckResult.get("CheckState")).isEqualTo("2");
67+
assertThat(copyrightCheckResult)
68+
.isNotNull()
69+
.containsEntry("Count", "2")
70+
.containsEntry("CheckState", "2");
7071

71-
assertThat(resultList.get(0).get("ArticleIdx")).isEqualTo("1");
72-
assertThat(resultList.get(0).get("UserDeclareState")).isEqualTo("0");
73-
assertThat(resultList.get(0).get("AuditState")).isEqualTo("2");
74-
assertThat(resultList.get(0).get("OriginalArticleUrl")).isEqualTo("Url_1");
75-
assertThat(resultList.get(0).get("OriginalArticleType")).isEqualTo("1");
76-
assertThat(resultList.get(0).get("CanReprint")).isEqualTo("1");
77-
assertThat(resultList.get(0).get("NeedReplaceContent")).isEqualTo("1");
78-
assertThat(resultList.get(0).get("NeedShowReprintSource")).isEqualTo("1");
72+
assertThat(resultList.get(0)).containsEntry("ArticleIdx", "1")
73+
.containsEntry("UserDeclareState", "0")
74+
.containsEntry("AuditState", "2")
75+
.containsEntry("OriginalArticleUrl", "Url_1")
76+
.containsEntry("OriginalArticleType", "1")
77+
.containsEntry("CanReprint", "1")
78+
.containsEntry("NeedReplaceContent", "1")
79+
.containsEntry("NeedShowReprintSource", "1");
7980

80-
assertThat(resultList.get(1).get("ArticleIdx")).isEqualTo("2");
81-
assertThat(resultList.get(1).get("UserDeclareState")).isEqualTo("0");
82-
assertThat(resultList.get(1).get("AuditState")).isEqualTo("2");
83-
assertThat(resultList.get(1).get("OriginalArticleUrl")).isEqualTo("Url_2");
84-
assertThat(resultList.get(1).get("OriginalArticleType")).isEqualTo("1");
85-
assertThat(resultList.get(1).get("CanReprint")).isEqualTo("1");
86-
assertThat(resultList.get(1).get("NeedReplaceContent")).isEqualTo("1");
87-
assertThat(resultList.get(1).get("NeedShowReprintSource")).isEqualTo("1");
81+
assertThat(resultList.get(1)).containsEntry("ArticleIdx", "2")
82+
.containsEntry("UserDeclareState", "0")
83+
.containsEntry("AuditState", "2")
84+
.containsEntry("OriginalArticleUrl", "Url_2")
85+
.containsEntry("OriginalArticleType", "1")
86+
.containsEntry("CanReprint", "1")
87+
.containsEntry("NeedReplaceContent", "1")
88+
.containsEntry("NeedShowReprintSource", "1");
89+
}
90+
91+
@Test
92+
public void testXml2Map_another() {
93+
String xml = "<xml> <ToUserName><![CDATA[gh_4d00ed8d6399]]></ToUserName> <FromUserName><![CDATA[oV5CrjpxgaGXNHIQigzNlgLTnwic]]></FromUserName> <CreateTime>1481013459</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[PUBLISHJOBFINISH]]></Event> <PublishEventInfo> <publish_id>2247503051</publish_id> <publish_status>0</publish_status> <article_id><![CDATA[b5O2OUs25HBxRceL7hfReg-U9QGeq9zQjiDvy WP4Hq4]]></article_id> <article_detail> <count>1</count> <item> <idx>1</idx> <article_url><![CDATA[ARTICLE_URL]]></article_url> </item> <item> <idx>2</idx> <article_url><![CDATA[ARTICLE_URL_2]]></article_url> </item> </article_detail> </PublishEventInfo> </xml>";
94+
95+
final Map<String, Object> map = XmlUtils.xml2Map(xml);
96+
assertThat(map).isNotNull()
97+
.containsEntry("ToUserName", "gh_4d00ed8d6399")
98+
.containsEntry("FromUserName", "oV5CrjpxgaGXNHIQigzNlgLTnwic")
99+
.containsEntry("CreateTime", "1481013459")
100+
.containsEntry("MsgType", "event");
101+
102+
Map<String, Object> publishEventInfo = (Map<String, Object>) map.get("PublishEventInfo");
103+
assertThat(publishEventInfo).containsEntry("publish_id", "2247503051")
104+
.containsEntry("publish_status", "0")
105+
.containsEntry("article_id", "b5O2OUs25HBxRceL7hfReg-U9QGeq9zQjiDvy WP4Hq4");
106+
107+
Map<String, Object> articleDetail = (Map<String, Object>) publishEventInfo.get("article_detail");
108+
assertThat(articleDetail).containsEntry("count", "1");
109+
List< Map<String, Object>> item = (List<Map<String, Object>>) articleDetail.get("item");
110+
assertThat(item.get(0)).containsEntry("idx", "1")
111+
.containsEntry("article_url", "ARTICLE_URL");
112+
113+
assertThat(item.get(1)).containsEntry("idx", "2")
114+
.containsEntry("article_url", "ARTICLE_URL_2");
88115
}
89116
}

0 commit comments

Comments
 (0)