如何借助XSD解析嵌套XML并在Java中构建结构化HashMap列表
实现方案
核心思路
针对嵌套XML,我们需要扁平化标签路径(用.分隔父节点与子节点)作为HashMap的key,标签文本作为value;同时定位XML中代表“行”的重复节点(比如业务数据中的<record>或<user>),每个这样的节点对应一个HashMap,最终收集为List<HashMap<String, String>>。
完整代码实现
import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class XmlToHashMapList { public static void main(String[] args) { try { // 初始化DOM解析器,过滤空白和注释节点 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setIgnoringElementContentWhitespace(true); factory.setIgnoringComments(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new File("your-data.xml")); doc.normalize(); // 定位到代表单行数据的重复节点(需根据你的XML结构修改标签名) NodeList rowNodes = doc.getElementsByTagName("user"); List<HashMap<String, String>> recordList = new ArrayList<>(); // 遍历每个行节点,构建对应的HashMap for (int i = 0; i < rowNodes.getLength(); i++) { Node rowNode = rowNodes.item(i); HashMap<String, String> record = new HashMap<>(); // 递归遍历子节点,扁平化路径并填充数据 traverseNode(rowNode, "", record); recordList.add(record); } // 测试输出结果 for (HashMap<String, String> map : recordList) { System.out.println(map); } } catch (Exception e) { e.printStackTrace(); } } /** * 递归遍历节点,扁平化路径并填充HashMap * @param node 当前处理的节点 * @param parentPath 父节点的路径(用于拼接当前节点的完整路径) * @param record 要填充的HashMap对象 */ private static void traverseNode(Node node, String parentPath, HashMap<String, String> record) { if (node.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) node; // 拼接当前节点的完整路径 String currentPath = parentPath.isEmpty() ? element.getTagName() : parentPath + "." + element.getTagName(); // 检查当前节点是否包含子元素 NodeList childNodes = element.getChildNodes(); boolean hasChildElements = false; for (int i = 0; i < childNodes.getLength(); i++) { Node child = childNodes.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { hasChildElements = true; traverseNode(child, currentPath, record); } } // 如果是叶子节点(无子元素),提取文本内容存入HashMap if (!hasChildElements) { String text = element.getTextContent().trim(); if (!text.isEmpty()) { record.put(currentPath, text); } } } } }
代码说明
- 解析器配置:通过
setIgnoringElementContentWhitespace和setIgnoringComments过滤干扰节点,避免空文本影响数据提取。 - 行节点定位:修改
getElementsByTagName("user")中的标签名,替换为你XML中代表单行数据的重复节点(比如<order>、<product>)。 - 递归遍历逻辑:
traverseNode方法自动拼接嵌套标签的路径,仅提取叶子节点的文本内容,确保HashMap的key是唯一的扁平化路径。
示例输出(对应嵌套XML)
假设你的XML结构如下:
<root> <user> <id>1</id> <name>Alice</name> <contact> <email>alice@test.com</email> <phone>123456</phone> </contact> </user> <user> <id>2</id> <name>Bob</name> <contact> <email>bob@test.com</email> <phone>654321</phone> </contact> </user> </root>
运行代码后,输出的List
{id=1, name=Alice, contact.email=alice@test.com, contact.phone=123456} {id=2, name=Bob, contact.email=bob@test.com, contact.phone=654321}
扩展处理
- 提取属性:若需要提取XML元素的属性,可在
traverseNode方法中添加属性遍历逻辑,比如:NamedNodeMap attrs = element.getAttributes(); for (int j = 0; j < attrs.getLength(); j++) { Attr attr = (Attr) attrs.item(j); String attrKey = currentPath + "@" + attr.getName(); record.put(attrKey, attr.getValue()); } - XSD约束校验:如果需要遵循XSD的字段约束,可在解析完成后添加校验逻辑,确保HashMap包含必填字段。
内容的提问来源于stack exchange,提问作者Yashwin.L
相关产品推荐
相关产品推荐

