如何使用Apache Groovy的XmlSlurper为XML属性添加命名空间?
问题:为XML空元素添加xsi:nil属性
我正在遍历扁平化XML的子元素,需要为空元素添加特定属性。现有代码如下:
import groovy.xml.XmlUtil import groovy.xml.MarkupBuilder import groovy.xml.XmlSlurper def xmlTxt = '''<root> <node> <element/> <element/> </node> </root>''' def xml = new XmlSlurper().parseText(xmlTxt) xml.node.'*'.each { if ( it == "") { it.'@foo' = "bar" } } return XmlUtil.serialize(xml)
运行结果为:
<?xml version="1.0" encoding="UTF-8"?><root> <node> <element foo="bar"/> <element foo="bar"/> </node> </root>
我的实际需求是将元素修改为<element xsi:nil="true"/>,其中xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"。我尝试在创建XmlSlurper实例时使用.declareNamespace(xsi:'http://www.w3.org/2001/XMLSchema-instance'),然后在添加属性时使用it.'@xsi:nil' = 'true',但这会导致错误。请问有没有使用现有语法快速实现的方法?
解决方案
直接通过XmlSlurper处理带命名空间的属性时,不需要提前声明命名空间,改用attributes().put()方法即可避开报错,具体实现有两种方式:
方式1:在每个空元素上声明命名空间
import groovy.xml.XmlUtil import groovy.xml.XmlSlurper def xmlTxt = '''<root> <node> <element/> <element/> </node> </root>''' def xml = new XmlSlurper().parseText(xmlTxt) xml.node.'*'.each { elem -> if (elem == "") { elem.attributes().put("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") elem.attributes().put("xsi:nil", "true") } } return XmlUtil.serialize(xml)
运行结果
<?xml version="1.0" encoding="UTF-8"?><root> <node> <element xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/> <element xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/> </node> </root>
方式2:在根节点统一声明命名空间(更规范)
如果希望命名空间只在根节点声明,避免重复,可以先给根节点添加命名空间属性,再给空元素添加xsi:nil:
import groovy.xml.XmlUtil import groovy.xml.XmlSlurper def xmlTxt = '''<root> <node> <element/> <element/> </node> </root>''' def xml = new XmlSlurper().parseText(xmlTxt) // 根节点添加xsi命名空间 xml.attributes().put("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") xml.node.'*'.each { elem -> if (elem == "") { elem.attributes().put("xsi:nil", "true") } } return XmlUtil.serialize(xml)
运行结果
<?xml version="1.0" encoding="UTF-8"?><root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <node> <element xsi:nil="true"/> <element xsi:nil="true"/> </node> </root>
内容的提问来源于stack exchange,提问作者Axel K.
相关产品推荐
相关产品推荐

