Reputation: 14971
I have a simple Groovy method that uses Groovy's MarkupBuilder to print HTML, very simplified version below:
void writeHtmlFile(<args>) {
def writer = new FileWriter(fileName.toFile())
def html = new MarkupBuilder(writer)
html.mkp.yieldUnescaped '<!DOCTYPE html>'
html.mkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
html.html {
head { ... }
body(id: 'main') {
h1 "Report Title"
}
}
writer.flush()
writer.close()
}
This works well. Say I wanted to call a method after the h1
that does some calculations and adds more to the MarkupBuilder. How do I get the elements defined in the called method added to the MarkupBuilder? Here's something I tried that doesn't cause an exception, but also doesn't work (the resulting HTML has no <h2>
element):
Closure testNested() {
println '---'
return { h2 "here's a subheading" }
}
// .... other stuff from above example not repeated ...
html.html {
head {...}
body(id: 'main') {
h1 "Report Title"
testNested()
}
I know I can easily do this inline. I'm trying to deepen my understanding of how Groovy uses closures and delegates in DSLs and clearly I'm missing something.
Upvotes: 0
Views: 669
Reputation: 24498
Consider the following code, which executes fine for me, using Groovy 2.4.5.
The builder pattern is a bit tricky because it can be viewed as hierarchical data and/or code, depending on your perspective. With practice, one can switch perspectives as necessary.
import groovy.xml.*
void testNested(def html) {
html.h2("here's a subheading from testNested")
}
void writeHtmlFile(def fileName) {
def writer = new FileWriter(fileName)
def html = new MarkupBuilder(writer)
html.mkp.yieldUnescaped '<!DOCTYPE html>'
html.mkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
html.html {
body(id: 'main') {
h1 "Report Title"
testNested(html)
}
}
writer.flush()
writer.close()
}
writeHtmlFile("out.html")
Upvotes: 2