Builders
28.1 MarkupBuilder (XML/HTML)
StreamingMarkupBuilder for large documents (with namespaces and mkp.yieldUnescaped).
import groovy.xml.MarkupBuilder
def writer = new StringWriter()
def html = new MarkupBuilder(writer)
html.html {
head { title "Groovy Builder" }
body {
h1 class: "title", "Welcome"
ul {
['Ana', 'Bo'].each { name -> li name }
}
a href: "https://groovy-lang.org", "Groovy"
}
}
println writer28.2 JsonBuilder and StreamingJsonBuilder
import groovy.json.JsonBuilder
def json = new JsonBuilder()
json.person {
name "Ana"
age 30
skills "Groovy", "Java"
address(city: "Pune", zip: "411001")
}
println json.toPrettyString()
def list = new JsonBuilder([1, 2, 3])
def sw = new StringWriter()
new groovy.json.StreamingJsonBuilder(sw).users([[id: 1], [id: 2]])28.3 Other Builders
Generic tree of Nodes Build object graphs (beans) Create directory/file structures SwingBuilder / groovy-swing Run Ant tasks (ant.copy(todir:...)) Command-line parsing (Module 38) YamlBuilder / TomlBuilder YAML / TOML (Groovy 3+/4+)
def tree = new FileTreeBuilder(new File("project"))
tree.dir("src") {
dir("main") { file("App.groovy", "println 'hi'") }
file("README.md") { withWriter('UTF-8') { it << "# Project" } }
}
def ant = new AntBuilder()
ant.zip(destfile: "out.zip", basedir: "project")28.4 Writing Your Own Builder
Or use FactoryBuilderSupport for factories per node type. Simple builders can just use methodMissing + closures.
class HtmlBuilder extends BuilderSupport {
def sb = new StringBuilder()
protected void setParent(Object parent, Object child) {}
protected Object createNode(Object name) { sb << "<$name>"; name }
protected Object createNode(Object name, Object value) { sb << "<$name>$value"; name }
protected Object createNode(Object name, Map attrs) { sb << "<$name ${attrs.collect { k, v -> "$k='$v'" }.join(' ')}>"; name }
protected Object createNode(Object name, Map attrs, Object value) { createNode(name, attrs); sb << value; name }
protected void nodeCompleted(Object parent, Object node) { sb << "</$node>" }
}
def b = new HtmlBuilder()
b.div(class: "box") { p "Hello" }
println b.sb