xml转为map工具类,可直接使用
-
背景:业务场景中遇见一个解读xml文件的需求,在搜索引擎泡了好久,都没能找到理想的解决方案,最终决定集大家之所长,将cv工程师的能力发挥到极致
,创立如下工具类,如有不足之处,还望多多补充!!! -
工具类代码如下:
package com.central.ls.utils; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Nullable; import javax.validation.constraints.NotNull; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** * xml解析工具类 * * @author: lix * @Date:2023-02-18 13:15:29 */ public class XmlAnalysisUtil { /** * 将xml文件转化为 map * @param multipartFile xml文件 * @param nodeNames 名称重复的,不属于最小子节点的节点名(解释:此节点还有子节点) * @param minimumNodeNames 名称重复的,属于最小子节点的节点名(解释:最小子节点意为此节点没有任何子节点) * @return * @throws IOException * @throws DocumentException */ public static Map<String,Object> xmlToLinkedMap(MultipartFile multipartFile, @Nullable Set<String> nodeNames, @Nullable Set<String> minimumNodeNames) throws IOException, DocumentException { // 获取文件名 String fileName = multipartFile.getOriginalFilename(); // 获取文件后缀 String prefix = fileName.substring(fileName.lastIndexOf(".")); //若须要防止生成的临时文件重复,能够在文件名后添加随机码 //转化为File File file = File.createTempFile(fileName, prefix); multipartFile.transferTo(file); //解析xml SAXReader reader = new SAXReader(); Document document = reader.read(file); Element root = document.getRootElement(); Map<String, Object> res = new LinkedHashMap<>(); return recursionXmlToMap(root, res,nodeNames,minimumNodeNames); } /** * multilayerXmlToMap核心方法,递归调用 * * @param element 节点元素 * @param outMap 用于存储xml数据的map */ @SuppressWarnings("unchecked") private static Map recursionXmlToMap(Element element, Map<String, Object> outMap, @Nullable Set<String> nodeNames, @Nullable Set<String> minimumNodeNames) { // 得到根元素下的子元素列表 List<Element> list = element.elements(); int size = list.size(); if (size == 0) { // 如果没有子元素,则将其存储进map中 if (ObjectUtil.isNotNull(minimumNodeNames)) { //节点名称重复,为了避免数据丢失,重命名节点, if (strEqualCollection(element.getName(),minimumNodeNames)) outMap.put(IdUtil.fastSimpleUUID(), element.getTextTrim()); else outMap.put(element.getName(), element.getTextTrim()); } else outMap.put(element.getName(), element.getTextTrim()); } else{ // 遍历子元素 Map<String, Object> innerMap = new LinkedHashMap<>(); list.forEach(childElement -> recursionXmlToMap(childElement, innerMap,nodeNames,minimumNodeNames) ); //名称重复的节点使用list保存 if (ObjectUtil.isNotNull(nodeNames)) { if (strEqualCollection(element.getName(), nodeNames)) { List<Map<String, Object>> insert = (List<Map<String, Object>>) outMap.get(element.getName()); innerMap.put(element.getName(), innerMap); if (!ObjectUtil.isNotEmpty(insert)) { insert = new ArrayList<>(); } insert.add(innerMap); outMap.put(element.getName(), insert); } else outMap.put(element.getName(), innerMap); }else outMap.put(element.getName(), innerMap); } return outMap; } /** * 判断一组字符串和某个字符串内容是否相等 * @param content 某个字符串 * @param compared 一组字符串 * @return 都不相等返回false,只要有一个相等则返回true */ private static boolean strEqualCollection (@NotNull String content, @NotNull Set<String> compared) { AtomicBoolean res = new AtomicBoolean(false); compared.forEach(c -> { if (content.equals(c)) res.set(true); }); return res.get(); } }
3.如何使用:
a. 所有节点名称都没有重复的情况:
/**
*此处的xml文件中所有节点的名称都不重复,所以nodeNames和minimunNodeNames都为空
**/
Map<String,Object> test = XmlAnalysisUtil.xmlToLinkedMap(xml,null,null);
附图:
b. 有重复节点名称,且该节点不为最小子节点
Set<String> nodeNames = new HashSet<>();
nodeNames.add("Test");
Map<String,Object> oae = XmlAnalysisUtil.xmlToLinkedMap(xml,nodeNames,null);
附图:
附图(xml文件):
c. 有重复节点名称,且该节点为最小子节点
/**
*xml 解释:MultipartFile xml参数
**/
Set<String> minimumNodeNames = new HashSet<>();
nodeNames.add("Test");
Map<String,Object> oae = XmlAnalysisUtil.xmlToLinkedMap(xml,null,minimumNodeNames);
该类情况没有遇到,不附图了;
d.有重复节点名称,且包含了最小子节点和非最小子节点
/**
*xml 解释:MultipartFile xml参数
**/
Set<String> nodeNames = new HashSet<>();
nodeNames.add("Test");
Set<String> minimumNodeNames = new HashSet<>();
nodeNames.add("Test");
Map<String,Object> oae = XmlAnalysisUtil.xmlToLinkedMap(xml,nodeNames,minimumNodeNames);
该类情况同c
简单说明一下,虽然没有自己测试过,但是代码肯定是没问题的,这点自信还是有的~~~,欢迎各位大神亲测!
其中的原理我的注释应该是写的很清楚了,如有不足之处,欢迎各位大神指出,感谢!!!
本文来自博客园,作者:六爻呈乾,转载请注明原文链接:https://www.cnblogs.com/ilycq/articles/17136871.html