Groovy for Domain-specific Languages - Second Edition

(nextflipdebug2) #1

Power Groovy DSL Features


[ 152 ]

To begin with, we define the root node of our XML by invoking
MarkupBuilder.customers() on the builder object. This causes a root
customers tag to be output into the XML stream and the code. The tag is not closed
off until the following closure is executed. This looks and behaves like a customer
method taking a closure as a parameter even though there is no such method.


Nested within the closure we come across more methods, such as calls to customer,
title, name, and address:


customer(id:1001) {
...

This method call will cause a new nested customer tag to be output into the XML
stream with an id attribute set to 1001. Once again, the tag is not closed off until the
closure is executed, during which more method-like calls are encountered:


title("Mr")
name(firstName:"Fred",surname:"Flintstone")
address(street:"1 Rock Road",city:"Bedrock")

No methods exist for customers, customer, title, name, or address.
MarkupBuilder, in conjunction with its base BuilderSupport class, uses the Groovy
MOP to make all of this work as if by magic. The beauty of this approach is how
intuitive the resulting code is, because it closely reflects the resulting markup. All we
need to remember is that pseudo-method call syntax will create a tag, and named
parameters will be inserted as attributes in the resulting output.


The parameters passed follow the same conventions that we discussed earlier in
relation to named parameters. In this case, all named parameters are collected and
become the attributes of the element. We should only pass one additional parameter,
which is used as the body of the tag or element.


GroovyMarkup and HTML


With MarkupBuilder, it's just as easy to build HTML pages. Here we generate a
simple HTML page:


given:
def writer = new StringWriter()
def html = new groovy.xml.MarkupBuilder(writer)

when:
html.html {
head {
title "Groovy Builders"

http://www.ebook3000.com
Free download pdf