diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/XmlUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/XmlUtils.java index 91c6b8f2e..7f7494431 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/XmlUtils.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/XmlUtils.java @@ -3,7 +3,6 @@ package me.chanjar.weixin.common.util; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxRuntimeException; import org.dom4j.*; import org.dom4j.io.SAXReader; @@ -15,6 +14,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** *
@@ -50,8 +50,8 @@ public class XmlUtils {
 
   private static Object element2MapOrString(Element element) {
 
-    final List content = element.content();
-    final Set names = names(content);
+    final List nodes = element.content();
+    final List names = names(nodes);
 
     // 判断节点下有无非文本节点(非Text和CDATA),如无,直接取Text文本内容
     if (names.size() < 1) {
@@ -59,10 +59,11 @@ public class XmlUtils {
     }
 
     Map result = Maps.newHashMap();
-    if (names.size() == 1) {
+    Set distinctNames = Sets.newHashSet(names);
+    if (distinctNames.size() == 1) {
       // 说明是个列表,各个子对象是相同的name
       List list = Lists.newArrayList();
-      for (Node node : content) {
+      for (Node node : nodes) {
         if (node instanceof DefaultText) {
           continue;
         }
@@ -73,8 +74,8 @@ public class XmlUtils {
       }
 
       result.put(names.iterator().next(), list);
-    } else {
-      for (Node node : content) {
+    } else if (distinctNames.size() == names.size()) {
+      for (Node node : nodes) {
         if (node instanceof DefaultText) {
           continue;
         }
@@ -83,13 +84,38 @@ public class XmlUtils {
           result.put(node.getName(), element2MapOrString((Element) node));
         }
       }
+    } else {
+      // 说明有重复name,但不是全部都相同
+      Map 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 values;
+            if (result.containsKey(nodeName)) {
+              values = (List) result.get(nodeName);
+            } else {
+              values = Lists.newArrayList();
+              result.put(nodeName, values);
+            }
+
+            values.add(element2MapOrString((Element) node));
+          }
+        }
+      }
     }
 
     return result;
   }
 
-  private static Set names(List nodes) {
-    Set names = Sets.newHashSet();
+  private static List names(List nodes) {
+    List names = Lists.newArrayList();
     for (Node node : nodes) {
       // 如果节点类型是Text或CDATA跳过
       if (node instanceof DefaultText || node instanceof CDATA) {
diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/XmlUtilsTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/XmlUtilsTest.java
index 7b6bb536f..ff34475ef 100644
--- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/XmlUtilsTest.java
+++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/XmlUtilsTest.java
@@ -63,27 +63,54 @@ public class XmlUtilsTest {
     assertThat(map).isNotNull();
     final Map copyrightCheckResult = (Map) map.get("CopyrightCheckResult");
     List> resultList = (List>) ((Map) copyrightCheckResult.get("ResultList")).get("item");
-    assertThat(copyrightCheckResult).isNotNull();
 
-    assertThat(copyrightCheckResult.get("Count")).isEqualTo("2");
-    assertThat(copyrightCheckResult.get("CheckState")).isEqualTo("2");
+    assertThat(copyrightCheckResult)
+      .isNotNull()
+      .containsEntry("Count", "2")
+      .containsEntry("CheckState", "2");
 
-    assertThat(resultList.get(0).get("ArticleIdx")).isEqualTo("1");
-    assertThat(resultList.get(0).get("UserDeclareState")).isEqualTo("0");
-    assertThat(resultList.get(0).get("AuditState")).isEqualTo("2");
-    assertThat(resultList.get(0).get("OriginalArticleUrl")).isEqualTo("Url_1");
-    assertThat(resultList.get(0).get("OriginalArticleType")).isEqualTo("1");
-    assertThat(resultList.get(0).get("CanReprint")).isEqualTo("1");
-    assertThat(resultList.get(0).get("NeedReplaceContent")).isEqualTo("1");
-    assertThat(resultList.get(0).get("NeedShowReprintSource")).isEqualTo("1");
+    assertThat(resultList.get(0)).containsEntry("ArticleIdx", "1")
+      .containsEntry("UserDeclareState", "0")
+      .containsEntry("AuditState", "2")
+      .containsEntry("OriginalArticleUrl", "Url_1")
+      .containsEntry("OriginalArticleType", "1")
+      .containsEntry("CanReprint", "1")
+      .containsEntry("NeedReplaceContent", "1")
+      .containsEntry("NeedShowReprintSource", "1");
 
-    assertThat(resultList.get(1).get("ArticleIdx")).isEqualTo("2");
-    assertThat(resultList.get(1).get("UserDeclareState")).isEqualTo("0");
-    assertThat(resultList.get(1).get("AuditState")).isEqualTo("2");
-    assertThat(resultList.get(1).get("OriginalArticleUrl")).isEqualTo("Url_2");
-    assertThat(resultList.get(1).get("OriginalArticleType")).isEqualTo("1");
-    assertThat(resultList.get(1).get("CanReprint")).isEqualTo("1");
-    assertThat(resultList.get(1).get("NeedReplaceContent")).isEqualTo("1");
-    assertThat(resultList.get(1).get("NeedShowReprintSource")).isEqualTo("1");
+    assertThat(resultList.get(1)).containsEntry("ArticleIdx", "2")
+      .containsEntry("UserDeclareState", "0")
+      .containsEntry("AuditState", "2")
+      .containsEntry("OriginalArticleUrl", "Url_2")
+      .containsEntry("OriginalArticleType", "1")
+      .containsEntry("CanReprint", "1")
+      .containsEntry("NeedReplaceContent", "1")
+      .containsEntry("NeedShowReprintSource", "1");
+  }
+
+  @Test
+  public void testXml2Map_another() {
+    String xml = "   1481013459    2247503051 0   1  1    2     ";
+
+    final Map map = XmlUtils.xml2Map(xml);
+    assertThat(map).isNotNull()
+      .containsEntry("ToUserName", "gh_4d00ed8d6399")
+      .containsEntry("FromUserName", "oV5CrjpxgaGXNHIQigzNlgLTnwic")
+      .containsEntry("CreateTime", "1481013459")
+      .containsEntry("MsgType", "event");
+
+    Map publishEventInfo = (Map) map.get("PublishEventInfo");
+    assertThat(publishEventInfo).containsEntry("publish_id", "2247503051")
+      .containsEntry("publish_status", "0")
+      .containsEntry("article_id", "b5O2OUs25HBxRceL7hfReg-U9QGeq9zQjiDvy WP4Hq4");
+
+    Map articleDetail = (Map) publishEventInfo.get("article_detail");
+    assertThat(articleDetail).containsEntry("count", "1");
+    List< Map> item = (List>) 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");
   }
 }