🎨 XmlUtils工具类优化,支持变态微信消息

This commit is contained in:
Binary Wang 2022-03-06 22:32:55 +08:00
parent 2c27f8bc5a
commit 61f1179bdb
2 changed files with 81 additions and 28 deletions

View File

@ -3,7 +3,6 @@ package me.chanjar.weixin.common.util;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.error.WxRuntimeException; import me.chanjar.weixin.common.error.WxRuntimeException;
import org.dom4j.*; import org.dom4j.*;
import org.dom4j.io.SAXReader; import org.dom4j.io.SAXReader;
@ -15,6 +14,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
/** /**
* <pre> * <pre>
@ -50,8 +50,8 @@ public class XmlUtils {
private static Object element2MapOrString(Element element) { private static Object element2MapOrString(Element element) {
final List<Node> content = element.content(); final List<Node> nodes = element.content();
final Set<String> names = names(content); final List<String> names = names(nodes);
// 判断节点下有无非文本节点(非Text和CDATA)如无直接取Text文本内容 // 判断节点下有无非文本节点(非Text和CDATA)如无直接取Text文本内容
if (names.size() < 1) { if (names.size() < 1) {
@ -59,10 +59,11 @@ public class XmlUtils {
} }
Map<String, Object> result = Maps.newHashMap(); Map<String, Object> result = Maps.newHashMap();
if (names.size() == 1) { Set<String> distinctNames = Sets.newHashSet(names);
if (distinctNames.size() == 1) {
// 说明是个列表各个子对象是相同的name // 说明是个列表各个子对象是相同的name
List<Object> list = Lists.newArrayList(); List<Object> list = Lists.newArrayList();
for (Node node : content) { for (Node node : nodes) {
if (node instanceof DefaultText) { if (node instanceof DefaultText) {
continue; continue;
} }
@ -73,8 +74,8 @@ public class XmlUtils {
} }
result.put(names.iterator().next(), list); result.put(names.iterator().next(), list);
} else { } else if (distinctNames.size() == names.size()) {
for (Node node : content) { for (Node node : nodes) {
if (node instanceof DefaultText) { if (node instanceof DefaultText) {
continue; continue;
} }
@ -83,13 +84,38 @@ public class XmlUtils {
result.put(node.getName(), element2MapOrString((Element) node)); result.put(node.getName(), element2MapOrString((Element) node));
} }
} }
} else {
// 说明有重复name但不是全部都相同
Map<String, Long> namesCountMap = names.stream().collect(Collectors.groupingBy(a -> a, Collectors.counting()));
for (Node node : nodes) {
if (node instanceof DefaultText) {
continue;
}
if (node instanceof Element) {
String nodeName = node.getName();
if (namesCountMap.get(nodeName) == 1) {
result.put(nodeName, element2MapOrString((Element) node));
} else {
List<Object> values;
if (result.containsKey(nodeName)) {
values = (List<Object>) result.get(nodeName);
} else {
values = Lists.newArrayList();
result.put(nodeName, values);
}
values.add(element2MapOrString((Element) node));
}
}
}
} }
return result; return result;
} }
private static Set<String> names(List<Node> nodes) { private static List<String> names(List<Node> nodes) {
Set<String> names = Sets.newHashSet(); List<String> names = Lists.newArrayList();
for (Node node : nodes) { for (Node node : nodes) {
// 如果节点类型是Text或CDATA跳过 // 如果节点类型是Text或CDATA跳过
if (node instanceof DefaultText || node instanceof CDATA) { if (node instanceof DefaultText || node instanceof CDATA) {

View File

@ -63,27 +63,54 @@ public class XmlUtilsTest {
assertThat(map).isNotNull(); assertThat(map).isNotNull();
final Map<String, Object> copyrightCheckResult = (Map<String, Object>) map.get("CopyrightCheckResult"); final Map<String, Object> copyrightCheckResult = (Map<String, Object>) map.get("CopyrightCheckResult");
List<Map<String, Object>> resultList = (List<Map<String, Object>>) ((Map<String, Object>) copyrightCheckResult.get("ResultList")).get("item"); List<Map<String, Object>> resultList = (List<Map<String, Object>>) ((Map<String, Object>) copyrightCheckResult.get("ResultList")).get("item");
assertThat(copyrightCheckResult).isNotNull();
assertThat(copyrightCheckResult.get("Count")).isEqualTo("2"); assertThat(copyrightCheckResult)
assertThat(copyrightCheckResult.get("CheckState")).isEqualTo("2"); .isNotNull()
.containsEntry("Count", "2")
.containsEntry("CheckState", "2");
assertThat(resultList.get(0).get("ArticleIdx")).isEqualTo("1"); assertThat(resultList.get(0)).containsEntry("ArticleIdx", "1")
assertThat(resultList.get(0).get("UserDeclareState")).isEqualTo("0"); .containsEntry("UserDeclareState", "0")
assertThat(resultList.get(0).get("AuditState")).isEqualTo("2"); .containsEntry("AuditState", "2")
assertThat(resultList.get(0).get("OriginalArticleUrl")).isEqualTo("Url_1"); .containsEntry("OriginalArticleUrl", "Url_1")
assertThat(resultList.get(0).get("OriginalArticleType")).isEqualTo("1"); .containsEntry("OriginalArticleType", "1")
assertThat(resultList.get(0).get("CanReprint")).isEqualTo("1"); .containsEntry("CanReprint", "1")
assertThat(resultList.get(0).get("NeedReplaceContent")).isEqualTo("1"); .containsEntry("NeedReplaceContent", "1")
assertThat(resultList.get(0).get("NeedShowReprintSource")).isEqualTo("1"); .containsEntry("NeedShowReprintSource", "1");
assertThat(resultList.get(1).get("ArticleIdx")).isEqualTo("2"); assertThat(resultList.get(1)).containsEntry("ArticleIdx", "2")
assertThat(resultList.get(1).get("UserDeclareState")).isEqualTo("0"); .containsEntry("UserDeclareState", "0")
assertThat(resultList.get(1).get("AuditState")).isEqualTo("2"); .containsEntry("AuditState", "2")
assertThat(resultList.get(1).get("OriginalArticleUrl")).isEqualTo("Url_2"); .containsEntry("OriginalArticleUrl", "Url_2")
assertThat(resultList.get(1).get("OriginalArticleType")).isEqualTo("1"); .containsEntry("OriginalArticleType", "1")
assertThat(resultList.get(1).get("CanReprint")).isEqualTo("1"); .containsEntry("CanReprint", "1")
assertThat(resultList.get(1).get("NeedReplaceContent")).isEqualTo("1"); .containsEntry("NeedReplaceContent", "1")
assertThat(resultList.get(1).get("NeedShowReprintSource")).isEqualTo("1"); .containsEntry("NeedShowReprintSource", "1");
}
@Test
public void testXml2Map_another() {
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>";
final Map<String, Object> map = XmlUtils.xml2Map(xml);
assertThat(map).isNotNull()
.containsEntry("ToUserName", "gh_4d00ed8d6399")
.containsEntry("FromUserName", "oV5CrjpxgaGXNHIQigzNlgLTnwic")
.containsEntry("CreateTime", "1481013459")
.containsEntry("MsgType", "event");
Map<String, Object> publishEventInfo = (Map<String, Object>) map.get("PublishEventInfo");
assertThat(publishEventInfo).containsEntry("publish_id", "2247503051")
.containsEntry("publish_status", "0")
.containsEntry("article_id", "b5O2OUs25HBxRceL7hfReg-U9QGeq9zQjiDvy WP4Hq4");
Map<String, Object> articleDetail = (Map<String, Object>) publishEventInfo.get("article_detail");
assertThat(articleDetail).containsEntry("count", "1");
List< Map<String, Object>> item = (List<Map<String, Object>>) articleDetail.get("item");
assertThat(item.get(0)).containsEntry("idx", "1")
.containsEntry("article_url", "ARTICLE_URL");
assertThat(item.get(1)).containsEntry("idx", "2")
.containsEntry("article_url", "ARTICLE_URL_2");
} }
} }