java源码如下:
import io.micrometer.core.instrument.util.StringUtils;
import org.dom4j.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
public class XmlUtil {
public static Logger logger = LoggerFactory.getLogger(XmlUtil.class);
/**
* 需要调整的节点
*/
private static Map<String, String> NODE_NAME_MAP = new HashMap<>();
/**
* 将xml格式响应报文解析为Map格式(并去掉List列表中的第一个空节点,防止转换成javabean时报错)
*
* @param xml xml原始报文
* @return Map 解析结果
*/
public static Map<String, Object> xmlToMap(String xml) {
logger.info("开始执行xmlToMap方法,解析Xml为map");
try {
Document doc = DocumentHelper.parseText(xml);
Element rootElement = doc.getRootElement();
Map<String, Object> resultMap = new HashMap<>();
parseElementToMap(resultMap, rootElement);
logger.info("执行xmlToMap方法,解析Xml为map完成,解析结果为:resultMap = [{}]", resultMap);
return resultMap;
} catch (DocumentException e) {
logger.error("开始执行xmlToMap方法,解析Xml为map异常", e);
}
return null;
}
/**
* 使用递归调用将多层级xml转为map,(xml中不能存在空节点)
*
* @param map 响应结果集
* @param rootElement 节点元素
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static void parseElementToMap(Map<String, Object> map, Element rootElement) {
//获得当前节点的子节点
List<Element> elements = rootElement.elements();
int elementsSize = elements.size();
if (elementsSize == 0) {
//没有子节点说明当前节点是叶子节点,直接取值
String name = rootElement.getName();
String value = rootElement.getText();
map.put(name, value);
} else if (elementsSize == 1) {
String elementName = rootElement.getName();
String textTrim = rootElement.getTextTrim();
String parentName = rootElement.getParent().getName();
if (parentName.endsWith("List") && StringUtils.isBlank(textTrim)) {
if (!elementName.endsWith("List") && StringUtils.isNotBlank(elementName) && StringUtils.isBlank(textTrim)) {
NODE_NAME_MAP.put(parentName, elementName);
System.out.println("===>子节点名称为" + elementName);
}
}
//只有一个子节点说明不用考虑list的情况,继续递归
Map<String, Object> tempMap = new HashMap<>();
parseElementToMap(tempMap, elements.get(0));
map.put(elementName, tempMap);
} else {
//多个子节点的话就要考虑list的情况了,特别是当多个子节点有名称相同的字段时
Map<String, Object> tempMap = new HashMap<>();
for (Element element : elements) {
String elementName = element.getName();
String textTrim = element.getTextTrim();
logger.info("循环当前节点名称为: {}, 对应的值为:{}",elementName,textTrim);
String parentName = element.getParent().getName();
System.out.println("循环当前节点名称为" + parentName);
if (parentName.endsWith("List") && StringUtils.isBlank(textTrim)) {
if (!elementName.endsWith("List") && StringUtils.isNotBlank(elementName) && StringUtils.isBlank(textTrim)) {
String name = element.getName();
NODE_NAME_MAP.put(parentName, name);
System.out.println("===>子节点名称为" + name);
}
}
tempMap.put(element.getName(), null);
}
System.out.println("临时存储map----->" + tempMap);
Set<String> keySet = tempMap.keySet();
for (String nodeName : keySet) {
System.out.println("当前节点名称为:" + nodeName);
Namespace namespace = elements.get(0).getNamespace();
List<Element> sameElements = rootElement.elements(new QName(nodeName, namespace));
//如果同名的数目大于1则表示要构建list
int sameElementSize = sameElements.size();
if (sameElementSize > 1) {
List<Map> list = new ArrayList<Map>();
for (Element element : sameElements) {
Map<String, Object> sameTempMap = new HashMap<>();
parseElementToMap(sameTempMap, element);
list.add(sameTempMap);
}
map.put(nodeName, list);
} else {
//同名的数量不大于1直接递归
Map<String, Object> sameTempMap = new HashMap<>();
parseElementToMap(sameTempMap, sameElements.get(0));
if (NODE_NAME_MAP.containsKey(nodeName)) {
logger.info("列表中第一个空节点为:{}", nodeName);
String childName = NODE_NAME_MAP.get(nodeName);
Object object = sameTempMap.get(childName);
if(object == null){
Object childObj = sameTempMap.get(nodeName);
Map<String, Object> childMap = null ;
if(childObj instanceof Map){
childMap = (Map<String, Object>)childObj;
}
map.put(nodeName,childMap.get(childName));
}else{
map.put(nodeName,sameTempMap.get(childName));
}
} else if (sameTempMap.containsKey(nodeName)) {
logger.info("列表去重第一个空节点为:{}", nodeName);
map.put(nodeName, sameTempMap.get(nodeName));
} else {
map.put(nodeName, sameTempMap);
}
}
}
}
}
}
示例:多层级XML
A123456
jack
15
张三
25
三年级一班
50
26
24
小寒
第三层测试
第三层测试
三年级二班
40
23
17
public static void main(String[] args) {
String xmlStr5 = "\n" +
"\n" +
"\t\n" +
"\t\tA123456 \n" +
"\t\tjack \n" +
"\t\t15 \n" +
"\t\n" +
"\t\n" +
"\t\t张三 \n" +
"\t\t25 \n" +
"\t\t\n" +
"\t\t\t\n" +
"\t\t\t\t三年级一班 \n" +
"\t\t\t\t50 \n" +
"\t\t\t\t26 \n" +
"\t\t\t\t24 \n" +
"\t\t\t\t\n" +
"\t\t\t\t\t\n" +
"\t\t\t\t\t\t小寒 \n" +
"\t\t\t\t\t\t\n" +
"\t\t\t\t\t\t\t\n" +
"\t\t\t\t\t\t\t\t第三层测试\n" +
"\t\t\t\t\t\t\t\n" +
"\t\t\t\t\t\t\n" +
"\t\t\t\t\t\n" +
"\t\t\t\t\n" +
"\t\t\t\n" +
"\t\t\t\n" +
"\t\t\t\t\n" +
"\t\t\t\t\t\n" +
"\t\t\t\t\t\t第三层测试\n" +
"\t\t\t\t\t\n" +
"\t\t\t\t\n" +
"\t\t\t\t三年级二班 \n" +
"\t\t\t\t40 \n" +
"\t\t\t\t23 \n" +
"\t\t\t\t17 \n" +
"\t\t\t\n" +
"\t\t\n" +
"\t\n" +
"";
try {
Map<String, Object> map = XmlUtil.xmlToMap(xmlStr5);
System.out.println(map);
} catch (Exception e) {
e.printStackTrace();
}