Groovy MarkupBuilder名称冲突

Groovy MarkupBuilder名称冲突,groovy,markupbuilder,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.grou

我有以下代码:

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>

样本组
样本伪影
1.0.0
请注意,缺少“标识”标记。。。我已经尝试了世界上的一切,以使该节点出现。我要把头发扯下来


提前感谢。

可能有更好的方法,但有一个技巧是直接调用
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,每个对象的签名都是
标识(闭包c)

这意味着,当您尝试在XML生成器上动态调用
identity
元素时,在传递单个闭包参数时,它正在调用
identity()
方法,这类似于在外部闭包上调用
delegate({…})

使用
invokeMethod
技巧迫使Groovy绕过元对象协议,将该方法视为动态方法,即使元对象上已经存在
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();
}

这更具可读性,意图更清晰,并且注释应该(希望)防止任何人删除“不必要的”空地图。

有效,但您能解释一下吗?什么是delegate?delegate.identity与delegate.invokeMethod('identity')为什么不同?仅供参考:我通过使用GroovyConsole检查XML对象找到了这一点。这让我知道,
identity
方法已经存在,它的参数是一个
闭包
。很好的解释和很好的解决方案!我在使用“版本”和“描述”字段时遇到了同样的问题,谢天谢地,在Github上搜索后,我找到了这个答案!