在Groovy中移除XML空标签及multimap标签的技术求助
解决XML移除multimap标签与空标签的问题
问题分析
需要处理带有SAP multimap命名空间的XML,核心目标:
- 移除所有
multimap:相关外层标签,替换为<base1> - 删除所有空标签(包括空
<budgets/>、无有效内容的<root>,以及未闭合的空<budgets>) - 仅保留包含实际数据的节点结构
现有代码的问题
- 字符串替换处理XML不可靠:直接用
replaceAll修改XML文本,容易破坏XML语法(比如命名空间处理不彻底、残留无效字符),无法处理XML的结构逻辑。 - 空节点移除逻辑不完整:
XmlParser的遍历仅从根节点移除空节点,没有递归处理子节点,也没过滤掉包含空节点的父节点(比如空<budgets>所在的<root>)。
正确的Groovy实现方案
以下代码通过XML解析器正确处理结构,递归移除空节点,同时替换multimap标签:
def body = message.getBody(java.lang.String) as String // 1. 解析XML,禁用外部DTD加载避免依赖问题 def parser = new XmlParser() parser.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false) parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false) def root = parser.parseText(body) // 2. 递归移除所有空节点(无文本、无子节点的节点) def removeEmptyNodes = { node -> // 先递归处理子节点,确保深层空节点先被清理 node.children().each { child -> if (child instanceof Node) { removeEmptyNodes(child) } } // 判断当前节点是否为空:无子节点且无有效文本 if (node.children().isEmpty() && (node.text() == null || node.text().trim().isEmpty())) { node.parent().remove(node) } } // 定位到multimap:Message1节点,清理其下的空节点 def messageNode = root.'multimap:Message1'[0] removeEmptyNodes(messageNode) // 3. 构建新的XML结构,替换为base1外层标签 def newRoot = new Node(null, 'base1') messageNode.children().each { child -> newRoot.append(child) } // 4. 生成格式化后的XML结果 def writer = new StringWriter() new XmlNodePrinter(new PrintWriter(writer)).print(newRoot) def result = writer.toString() // 将结果写回message message.setBody(result)
代码说明
- XML解析:使用
XmlParser并禁用DTD加载,避免解析时的外部依赖,同时正确处理命名空间。 - 递归清理空节点:先处理子节点再处理父节点,确保所有嵌套的空节点都被移除,连带过滤掉仅包含空节点的父节点(比如原来的空
<root>)。 - 结构重构:将清理后的有效节点,放到新的
<base1>标签下,保证输出结构符合预期。 - 格式化输出:用
XmlNodePrinter生成可读性良好的格式化XML。
验证结果
运行代码后会得到预期输出:
<base1> <root> <budgets> <id>1234</id> <field2>4496</field2> <field3>test</field3> </budgets> </root> </base1>
内容的提问来源于stack exchange,提问作者Sudha
相关产品推荐
相关产品推荐

