Groovy MarkupBuilder名称冲突

我有这个代码:

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>

请注意,“身份”标签丢失了…我已经尝试了世界上的所有内容来显示该节点.我正在撕开我的头发!

提前致谢.

可能有更好的方法,但一个技巧是直接调用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工作,这是常用的技巧.

编辑:我弄清楚发生了什么.

Groovy adds a method带有每个对象的标识(Closure c).

这意味着当您尝试动态调用XML构建器上的identity元素时,在传入单个闭包参数时,它调用了identity()方法,就像在外部闭包上调用delegate({…})一样.

使用invokeMethod技巧强制Groovy绕过元对象协议并将该方法视为动态方法,即使MetaObject上已存在标识方法.

了解这一点,我们可以将更好,更清晰的解决方案整合在一起.我们所要做的就是更改方法的签名,如下所示:

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();
}

这更具可读性,意图更清晰,评论应该(希望)阻止任何人删除“不必要的”空地图.

https://stackoverflow.com/questions/11388838/groovy-markupbuilder-name-conflict

转载注明原文:Groovy MarkupBuilder名称冲突