Groovy MarkupBuilder 名称冲突 [英] Groovy MarkupBuilder name conflict

查看:21
本文介绍了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>

请注意缺少身份"标签...我已经尝试了世界上的所有方法来显示该节点.我在扯头发!

Notice that the "identity" tag is missing... I've tried everything in the world to get that node to appear. I'm ripping my hair out!

提前致谢.

推荐答案

可能有更好的方法,但一个技巧是直接调用 invokeMethod:

There might be a better way, but one trick is to call invokeMethod directly:

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.identityowner.identity 工作,这是通常的技巧.

This is effectively what Groovy is doing behind the scenes. I couldn't get delegate.identity or owner.identity to work, which are the usual tricks.

编辑:我知道发生了什么.

Groovy 为每个对象添加一个带有 identity(Closure c) 签名的方法.

Groovy adds a method with a signature of identity(Closure c) to every object.

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

This means that when you tried to dynamically invoke the identity element on the XML builder, while passing in a single closure argument, it was calling the identity() method, which is like calling delegate({...}) on the outer closure.

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

Using the invokeMethod trick forces Groovy to bypass the Meta Object Protocol and treat the method as a dynamic method, even though the identity method already exists on the MetaObject.

知道了这一点,我们就可以组合出一个更好、更清晰的解决方案.我们所要做的就是改变方法的签名,像这样:

Knowing this, we can put together a better, more legible solution. All we have to do is change the signature of the method, like so:

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

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

This is much more readable, it's clearer the intent, and the comment should (hopefully) prevent anyone from removing the "unnecessary" empty map.

这篇关于Groovy MarkupBuilder 名称冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆