Giovanni Botta Giovanni Botta - 1 month ago 5
Groovy Question

Groovy NodeBuilder: how to pass closures around

I apologize in advance for the newbie question, but here it is. Let's say I am trying to generate markup using Groovy's

NodeBuilder
. I'd like to write something like the following:

nodes = {
'element'(key:'value')
'element'(blah:'123')
}
def createMarkup(additionalElements) {
def result = new groovy.xml.MarkupBuilder().root{
someElement(){
element(y: 'uh oh')
additionalElements() // does not work this way!
element(z: 'yeah')
}
}
}

createMarkup(nodes)


which results in:

<root>
<someElement>
<element y='uh oh' />
<element z='yeah' />
</someElement>
</root>


In a nutshell, what I'm trying to do is to have one (or more) externally defined closure(s) that I can pass to my
createMarkup()
and then stick at the right level in the tree, i.e., I'd like it to generate this:

<root>
<someElement>
<element y='uh oh' />
<element key='value' />
<element blah='123' />
<element z='yeah' />
</someElement>
</root>


How can I achieve this?

Answer

Found the solution:

nodes = { builder ->
  builder.element(key:'value')
  builder.element(blah:'123') 
}    

def createMarkup(additionalElements) {    
  def builder = new groovy.xml.MarkupBuilder()
  def result = builder.root{
    someElement(){
      element(y: 'uh oh')  
      additionalElements(builder)
      element(z: 'yeah')
    }
  }
}

createMarkup(nodes)

works as expected.