基于有序列表解析XML:Java DOM递归实现的节点关联疑问
问题描述
需要将以下CSV格式的层级数据:
order, xml_parent, xml_field 1,Identification,Id 2,Identification.Name,LastName 3,Identification.Name,FirstName 4,Identification.OfficialAddress,StreetName 5,Identification.OfficialAddress,StreetNumber 7,Identification.OfficialAddress,PostalCode 8,Identification.OfficialAddress,City 9,Identification.OfficialAddress,Country 10,Identification.Nationality 13,ReasonIntroduction.AskSomething,FromDate 14,ReasonIntroduction.AskMore,FirstTime
转换为指定结构的XML:
<root> <Identification> <Id>1</Id> <Name> <LastName>x</LastName> <FirstName>x</FirstName> </Name> <OfficialAddress> <StreetName>Fifth av.</StreetName> <StreetNumber>5</StreetNumber> <PostalCode>3212</PostalCode> <City>3212</City> <Country>UK</Country> </OfficialAddress> <Nationality>Qatar</Nationality> </Identification> <ReasonIntroduction> <AskSomething>true</AskSomething> <AskMore>true</AskMore> </ReasonIntroduction> </root>
计划用Java DOM解析实现,希望采用递归方式而非循环,但不清楚如何分组同层级元素(比如将Identification.Name下的LastName和FirstName纳入同一个<Name>节点),已有部分代码片段:
List<String> parentList = Arrays.asList(parentXmlName.split("\\.", -1)); Element parentElement = document.createElement(field.getXmlParentName()); Element element = document.createElement(field.getXmlName()); element.setTextContent(field.getValue()); parentElement.appendChild(element);
递归实现思路
1. 先将扁平CSV数据转换为树形映射
递归的核心前提是有清晰的层级结构,所以第一步要把CSV的扁平数据转换成树形结构的映射(用Map<String, Object>模拟:节点名作为key,值如果是String表示叶子节点的文本,Map表示子节点集合)。
示例实现代码:
// 假设你已有存储字段的实体类 class Field { private String xmlParent; private String xmlField; private String value; // 省略getter、构造方法 } // 构建树形映射的方法 private Map<String, Object> buildTreeMap(List<Field> fields) { Map<String, Object> rootMap = new HashMap<>(); for (Field field : fields) { // 拆分父路径为节点数组 String[] parentNodes = field.getXmlParent().split("\\.", -1); Map<String, Object> currentMap = rootMap; // 遍历父路径,创建中间节点的Map for (String nodeName : parentNodes) { currentMap = currentMap.computeIfAbsent(nodeName, k -> new HashMap<String, Object>()); } // 将当前字段作为叶子节点加入最终的父Map currentMap.put(field.getXmlField(), field.getValue()); } return rootMap; }
这个方法会把所有字段按层级嵌套,比如Identification.Name.LastName会被整理为rootMap -> "Identification" -> "Name" -> "LastName": "x"。
2. 递归遍历树形映射生成XML节点
有了树形映射后,编写递归方法遍历结构,逐个创建DOM元素:
private void buildXmlFromTree(Document doc, Element parentElement, Map<String, Object> nodeMap) { for (Map.Entry<String, Object> entry : nodeMap.entrySet()) { String nodeName = entry.getKey(); Object value = entry.getValue(); Element currentElement = doc.createElement(nodeName); if (value instanceof String) { // 叶子节点:设置文本内容 currentElement.setTextContent((String) value); parentElement.appendChild(currentElement); } else if (value instanceof Map) { // 非叶子节点:递归处理子节点 parentElement.appendChild(currentElement); buildXmlFromTree(doc, currentElement, (Map<String, Object>) value); } } }
3. 整合流程生成完整XML
将预处理、递归生成逻辑与DOM初始化整合:
// 假设已读取到所有Field的列表List<Field> fieldList DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.newDocument(); // 创建根节点<root> Element rootElement = doc.createElement("root"); doc.appendChild(rootElement); // 构建树形映射 Map<String, Object> treeMap = buildTreeMap(fieldList); // 递归生成XML结构 buildXmlFromTree(doc, rootElement, treeMap); // 后续可将doc输出为XML字符串或文件,此处省略输出逻辑
关键说明
- 递归的核心是先构建层级数据结构,树形映射已经把同层级元素归到了同一个父节点下,无需手动跟踪"下一个元素",递归只需专注于当前节点的子节点处理即可。
- 这种方式把数据整理和节点生成解耦,逻辑更清晰,也完全符合递归的思想。
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

