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

查看:160
本文介绍了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>
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:// '){
delegate.invokeMethod('identity',[{
groupId(catalog.groupId)
artifactId(catalog.artifactId)
版本(catalog.version)
}])
}

返回writer.toString();
}

这就是Groovy在幕后做的事情。我无法得到 delegate.identity owner.identity 来工作,这是常用的技巧。






编辑:我弄清楚发生了什么事情。

Groovy 为每个对象添加一个方法,其签名为 identity(Closure c)

这意味着,当您试图动态调用XML构建器上的标识元素时,传递一个闭包参数时,它调用 identity()方法,就像在外部闭包中调用委托({...})一样。



使用 invokeMethod 特技强制Groovy绕过元对象协议并将该方法视为动态方法,即使 identity 方法已经存在于MetaObject中。



知道这一点,我们可以制定一个更好,更清晰的解决方案。

 字符串buildCatalog(目录编目){$ b $所有我们要做的就是更改方法的签名,如下所示: b 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();
}

这可读性更强,意图更清晰,评论应该希望)防止任何人删除不必要的空白地图。


I have this code:

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

It produces this 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!

Thanks in advance.

解决方案

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

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.


Edit: I figured out what's going on.

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

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.

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天全站免登陆