Groovy中能否将待修改节点属性定义为变量并赋值?
动态修改XML节点属性(用变量指定属性名)
当然可以实现这个需求!你遇到的问题应该是Groovy语法使用不当导致的——直接用变量名作为属性访问的话,Groovy会把它当成字面量的属性名,而不是变量存储的属性名。咱们来一步步解决:
首先,先补全你的测试代码(你的XML片段没写完),方便演示:
import groovy.xml.* def myTest = '''<test:main xmlns:xmi="http://www.omg.org/XMI" xmlns:test="http://www.testexample.com/test"> <childNode xmi:id="_9_RgZj4lEeiL8o0bAkMKoA" name="Boo!" number="1.414"/> <childNode xmi:id="_9_RgYz4lEeiL8o0bAkMKoA" name="toto" number="42"/> <childNode xmi:id="__o_QMT4lEeiL8o0bAkMKoA" name="foo" number="3.14"/> </test:main>'''
核心解决方案:动态属性访问
要通过变量指定属性名并修改值,你需要用Groovy的GString属性访问语法,或者直接操作节点的属性Map。
方式1:用GString语法访问属性
这种方式最直观,适合普通属性(非命名空间属性):
// 解析XML def xml = new XmlSlurper(false, false).parseText(myTest) // 定义要修改的属性名和新值(这里可以换成你自己的变量逻辑) def targetAttr = 'name' def newValue = 'Updated_Boo' // 找到目标节点并动态设置属性 xml.childNode.find { it.@name == 'Boo!' }.each { node -> // 关键:用"$targetAttr"让Groovy解析变量值作为属性名 node."$targetAttr" = newValue } // 输出修改后的XML def writer = new StringWriter() XmlUtil.serialize(xml, writer) println writer.toString()
方式2:操作属性Map
如果你更习惯Map的操作方式,可以直接获取节点的属性集合来修改:
xml.childNode.find { it.@number == '42' }.each { node -> def targetAttr = 'number' def newValue = '99.99' // attributes()方法返回节点的属性Map,直接通过key(变量)修改 node.attributes()[targetAttr] = newValue }
处理带命名空间的属性
如果要修改的是带命名空间的属性(比如xmi:id),需要先创建命名空间对象,再用变量引用它:
// 定义命名空间 def xmiNs = new groovy.xml.Namespace('http://www.omg.org/XMI', 'xmi') def targetAttr = xmiNs.id def newValue = 'New_Unique_Id' xml.childNode.first().each { node -> node."$targetAttr" = newValue }
为什么你的原代码失败?
如果之前你写的是类似node.targetAttr = newValue,Groovy会把targetAttr当成一个字面量的属性名(也就是去找节点上叫targetAttr的属性),而不是读取变量targetAttr里存储的属性名。用node."$targetAttr"的语法,Groovy才会解析变量的值作为要访问的属性名。
内容的提问来源于stack exchange,提问作者Thibault Santonja
相关产品推荐
相关产品推荐

