groovy.xml.XmlParser解析冒号分隔唯一属性时丢失属性问题
Groovy XmlParser处理后丢失命名空间声明问题解答
问题结论
首先明确:这不是groovy.xml.XmlParser的bug,属于XML解析器的标准行为。
原因说明
XML解析器默认只会识别元素名、属性名中使用的命名空间前缀,不会主动扫描属性值内部的文本内容判断命名空间是否被使用。你的示例中xs前缀仅出现在xsi:type的属性值xs:int中,XmlParser判定该命名空间未被实际使用,所以序列化时自动移除了未使用的命名空间声明,仅保留了确实用到的xsi命名空间。
解决方案
方案1:手动补全需保留的命名空间
序列化节点前手动给目标节点添加需要保留的命名空间声明即可,修改后的代码如下:
import groovy.xml.XmlParser class CreateSelectedXML { static void xmlHandling(List<String> listCodes, String TEST_FILE_NAME) { def docdup = new StringBuilder() // 预先定义需要保留的命名空间,避免硬编码重复 def retainedNamespaces = [ 'xmlns:xs': 'http://www.w3.org/2001/XMLSchema' ] // 优化:将XML解析放到循环外,仅解析一次即可,大幅提升性能 File input = new File(TEST_FILE_NAME) def doc = new XmlParser().parse(input) listCodes.each { code -> doc.findAll{it.@code == code[0].toString()}.each { // 手动添加命名空间到当前节点属性 it.attributes().putAll(retainedNamespaces) def temp = groovy.xml.XmlUtil.serialize(it).toString() docdup.append(temp) } } } } }
方案2:通用适配场景
如果需要处理大量带xsi:type属性的节点,可以写通用工具方法,遍历所有节点的xsi:type属性,提取属性值中的命名空间前缀,自动补全对应的命名空间声明即可。
额外优化提示
原代码中每次遍历listCodes元素都会重新解析XML文件,当XML文件较大或列表元素较多时性能损耗很高,上面修改后的代码已经将解析逻辑移到循环外,仅需解析一次即可。
内容的提问来源于stack exchange,提问作者Sasori
相关产品推荐
相关产品推荐

