2012-07-09 50 views
5

我有這樣的代碼: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> 

注意,「身份」標籤丟失......我已經在嘗試了一切世界去獲得該節點的出現。我把我的頭髮撕掉了!

在此先感謝。

回答

11

有可能是一個更好的辦法,但一招就是直接調用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.identityowner.identity的工作,這是通常的技巧。


編輯:我想通了,這是怎麼回事。

Groovy adds a method每個對象的簽名爲identity(Closure c)

這意味着,當你試圖動態地調用的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(); 
} 

這是更具可讀性,它更清晰的意圖,和註釋應該(希望)防止任何人刪除了「不必要的」空地圖。

+0

這有效,但你能解釋一下嗎?什麼是委託,爲什麼delegate.identity與delegate.invokeMethod('identity')不同? – 2012-07-09 04:32:15

+0

我想通了,我會更新我的答案。 – OverZealous 2012-07-09 07:02:34

+0

僅供參考:我通過使用GroovyConsole檢查XML對象來追蹤此情況。這讓我知道'identity'方法已經存在,只有一個'Closure'作爲它的參數。 – OverZealous 2012-07-09 07:08:40