2012-07-09 1 views
5

이 코드가있는 "정체성"태그가 없음을그루비 MarkupBuilder 이름 충돌

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

이 그루비는 뒤에서하고있는 효과적으로 것입니다. delegate.identity 또는 owner.identity을 사용할 수 없으므로 일반적인 트릭입니다.


편집 : 나는 무슨 일이 일어나고 있는지 알아 냈어.

Groovy adds a method 모든 개체에 identity(Closure c)의 서명이 있습니다.

은 외부 폐쇄에 delegate({...})를 호출처럼입니다 identity() 메소드를 호출하고, 하나의 폐쇄 인수를 전달하는 동안, 동적으로 XML 빌더에 identity 요소를 호출하려고 할 때 것을 의미한다.

invokeMethod 트릭을 사용하면 identity 메소드가 이미 MetaObject에 있어도 Groovy가 메타 오브젝트 프로토콜을 우회하여 동적 메소드로 강제 처리합니다.

이 사실을 알게되면 더 잘 읽고 더 쉽게 읽을 수있는 솔루션을 만들 수 있습니다.

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.invokeMethod ('identity')와 다른가? –

+0

나는 그것을 알아 냈다. 나는 대답을 업데이트 할 것이다. – OverZealous

+0

FYI : GroovyConsole을 사용하여 XML 객체를 검사하여 추적했습니다. 이것은'identity '메소드가 이미 하나의'Closure'를 인자로 사용하여 존재했다는 것을 알려줍니다. – OverZealous