我有这样的代码:
String buildCatalog(Catalog catalog) {
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.catalog(xmlns:'http://www.sybrium.com/XMLSchema/NodeCatalog') {
'identity'() {
groupId(catalog.groupId)
artifactId(catalog.artifactId)
version(catalog.version)
}
}
return writer.toString();
}它生成以下xml:
<catalog xmlns='http://www.sybrium.com/XMLSchema/NodeCatalog'>
<groupId>sample.group</groupId>
<artifactId>sample-artifact</artifactId>
<version>1.0.0</version>
</catalog>请注意,"identity“标签丢失了...为了让那个节点出现,我尝试了世界上所有的方法。我要把头发拔出来了!
提前谢谢。
发布于 2012-07-09 12:20:14
也许有一种更好的方法,但是有一个技巧是直接调用invokeMethod:
String buildCatalog(Catalog catalog) {
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.catalog(xmlns:'http://www.sybrium.com/XMLSchema/NodeCatalog') {
delegate.invokeMethod('identity', [{
groupId(catalog.groupId)
artifactId(catalog.artifactId)
version(catalog.version)
}])
}
return writer.toString();
}这实际上就是Groovy在幕后做的事情。我无法让delegate.identity或owner.identity工作,这是常见的技巧。
编辑:我知道是怎么回事了。
对每个对象使用identity(Closure c)签名的Groovy adds a method。
这意味着,当您试图在传递单个闭包参数的同时动态调用XML构建器上的identity元素时,它调用的是identity()方法,这类似于在外部闭包上调用delegate({...})。
使用invokeMethod技巧会迫使Groovy绕过元对象协议,并将该方法视为动态方法,即使MetaObject上已经存在identity方法。
了解了这一点,我们就可以提出一个更好、更清晰的解决方案。我们所要做的就是更改方法的签名,如下所示:
String buildCatalog(Catalog catalog) {
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.catalog(xmlns:'http://www.sybrium.com/XMLSchema/NodeCatalog') {
// NOTE: LEAVE the empty map here to prevent calling the identity method!
identity([:]) {
groupId(catalog.groupId)
artifactId(catalog.artifactId)
version(catalog.version)
}
}
return writer.toString();
}这样做的可读性更好,意图更清晰,注释应该(希望)防止任何人删除“不必要的”空map。
https://stackoverflow.com/questions/11388838
复制相似问题