
- •Credits
- •About the Authors
- •About the Reviewers
- •www.PacktPub.com
- •Table of Contents
- •Preface
- •Introduction
- •Installing Groovy on Windows
- •Installing Groovy on Linux and OS X
- •Executing Groovy code from the command line
- •Using Groovy as a command-line text file editor
- •Running Groovy with invokedynamic support
- •Building Groovy from source
- •Managing multiple Groovy installations on Linux
- •Using groovysh to try out Groovy commands
- •Starting groovyConsole to execute Groovy snippets
- •Configuring Groovy in Eclipse
- •Configuring Groovy in IntelliJ IDEA
- •Introduction
- •Using Java classes from Groovy
- •Embedding Groovy into Java
- •Compiling Groovy code
- •Generating documentation for Groovy code
- •Introduction
- •Searching strings with regular expressions
- •Writing less verbose Java Beans with Groovy Beans
- •Inheriting constructors in Groovy classes
- •Defining code as data in Groovy
- •Defining data structures as code in Groovy
- •Implementing multiple inheritance in Groovy
- •Defining type-checking rules for dynamic code
- •Adding automatic logging to Groovy classes
- •Introduction
- •Reading from a file
- •Reading a text file line by line
- •Processing every word in a text file
- •Writing to a file
- •Replacing tabs with spaces in a text file
- •Deleting a file or directory
- •Walking through a directory recursively
- •Searching for files
- •Changing file attributes on Windows
- •Reading data from a ZIP file
- •Reading an Excel file
- •Extracting data from a PDF
- •Introduction
- •Reading XML using XmlSlurper
- •Reading XML using XmlParser
- •Reading XML content with namespaces
- •Searching in XML with GPath
- •Searching in XML with XPath
- •Constructing XML content
- •Modifying XML content
- •Sorting XML nodes
- •Serializing Groovy Beans to XML
- •Introduction
- •Parsing JSON messages with JsonSlurper
- •Constructing JSON messages with JsonBuilder
- •Modifying JSON messages
- •Validating JSON messages
- •Converting JSON message to XML
- •Converting JSON message to Groovy Bean
- •Using JSON to configure your scripts
- •Introduction
- •Creating a database table
- •Connecting to an SQL database
- •Modifying data in an SQL database
- •Calling a stored procedure
- •Reading BLOB/CLOB from a database
- •Building a simple ORM framework
- •Using Groovy to access Redis
- •Using Groovy to access MongoDB
- •Using Groovy to access Apache Cassandra
- •Introduction
- •Downloading content from the Internet
- •Executing an HTTP GET request
- •Executing an HTTP POST request
- •Constructing and modifying complex URLs
- •Issuing a REST request and parsing a response
- •Issuing a SOAP request and parsing a response
- •Consuming RSS and Atom feeds
- •Using basic authentication for web service security
- •Using OAuth for web service security
- •Introduction
- •Querying methods and properties
- •Dynamically extending classes with new methods
- •Overriding methods dynamically
- •Adding performance logging to methods
- •Adding transparent imports to a script
- •DSL for executing commands over SSH
- •DSL for generating reports from logfiles
- •Introduction
- •Processing collections concurrently
- •Downloading files concurrently
- •Splitting a large task into smaller parallel jobs
- •Running tasks in parallel and asynchronously
- •Using actors to build message-based concurrency
- •Using STM to atomically update fields
- •Using dataflow variables for lazy evaluation
- •Index

Working with XML in Groovy
See also
ff Reading XML using XmlSlurper ff Searching in XML with GPath
ff http://groovy.codehaus.org/api/groovy/util/XmlParser.html ff http://groovy.codehaus.org/api/groovy/util/Node.html
ff http://groovy.codehaus.org/api/groovy/util/NodeList.html ff http://groovy.codehaus.org/GPath
Reading XML content with namespaces
XML namespaces, in a way, are similar to Java packages because they allow creating an additional context for grouping a set of elements. We already noted some differences in namespace handling for the XmlParser and XmlSlurper classes in the Reading XML using XmlParser and Reading XML using XmlSlurper recipes.
In this recipe, we dig a bit deeper into the details of XML namespace support in Groovy.
Getting ready
Let's use the same shakespeare.xml file we used for the Reading XML using XmlParser and Reading XML using XmlSlurper recipes.
How to do it...
XmlParser requires you to specify an element name exactly as it appears in the parsed XML, including the name of the prefix used in the actual XML content. This makes the code fragile because the namespace prefixes have to match.
1.In order to make code that is based on XmlParser more reliable in respect to namespaces, we can resort to the groovy.xml.Namespace class as shown in the following code:
import groovy.xml.Namespace
def xmlSource = new File('shakespeare.xml')
def bibliography = new XmlParser().parse(xmlSource)
def bib = new Namespace('http://bibliography.org', 'bib') def lit = new Namespace('http://literature.org', 'lit')
println bibliography[bib.author].text() println bibliography[lit.play].findAll { it[lit.year].text().toInteger() > 1592
}.size()
172
www.it-ebooks.info

Chapter 5
2.XmlSlurper has a similar API for declaring the prefixes and namespaces required to navigate the nodes, shown in the following code:
def xmlSource = new File('shakespeare.xml')
def bibliography = new XmlSlurper().parse(xmlSource)
bibliography.declareNamespace( bib: 'http://bibliography.org', lit: 'http://literature.org')
println bibliography.'bib:author' println bibliography.'lit:play'.findAll {
it.'lit:year'.toInteger() > 1592 }.size()
3.The output of both scripts is indistinguishable:
William Shakespare 3
How it works...
Both of the previous code snippets extract the author's name and the number of plays written after 1592 from our reference bibliography data XML document.
In the case of XmlParser, we declare two instances of the groovy.xml.Namespace class. When we fetch a property (for example, bibliography[bib.author]) from the Namespace object, this is really what happens:
ff The bib.author expression returns a value of javax.xml.namespace.QName type.
ff The array reference bibliography[bib.author] is translated by Groovy into a call to the getAt method of the groovy.util.Node class. This method accepts a QName as an argument and returns a node if the QName is found, as shown next:
QName ns = bib.author
Node n = bibliography.getAt(ns)
In the case of XmlSlurper, the groovy.util.slurpersupport.GPathResult class instance (returned by the parse method) has an additional method to declare namespaces called, not surprisingly, declareNamespace.
173
www.it-ebooks.info

Working with XML in Groovy
Please note that unlike XmlParser, the XmlSlurper implementation (or more specifically GPathResult) does not force you to depend on
namespaces or prefixes at all. You can refer to elements and attributes using their local names, and only resort to using namespace prefixes if there are same local names under different namespaces.
If you try to use a fully qualified name (for example. bib:author) before declaring the namespace within an XmlSlurper instance, you'll get no result back. Also, namespace prefixes defined by declareNamespace do not have to match prefixes appearing in the actual XML file.
The declareNamespace method takes a map of prefixes and namespaces. When those are defined, you can use them to reference elements using their fully qualified names.
There's more...
If you plan to switch between XmlParser and XmlSlurper implementations and you need to parse XML that uses namespaces, then the safest approach is to use the *: prefix for element or attribute queries. For example:
println bibliography.'*:author'.text()
See also
ff Reading XML using XmlParser ff Reading XML using XmlSlurper ff Searching in XML with GPath
ff http://groovy.codehaus.org/api/groovy/util/XmlParser.html ff http://groovy.codehaus.org/api/groovy/util/XmlSlurper.html ff http://groovy.codehaus.org/api/groovy/util/Node.html
ff http://groovy.codehaus.org/api/groovy/xml/Namespace.html
174
www.it-ebooks.info

Chapter 5
Searching in XML with GPath
When using XmlSlurper or XmlParser with Groovy (see the Reading XML using XmlSlurper and Reading XML using XmlParser recipes), the returned parsed result can be queried
using GPath. GPath is a way to navigate nested data structures in Groovy. Sometimes GPath is called an expression language integrated into Groovy; but, in fact, GPath does not have
a separate compiler or interpreter, it's just the way Groovy language and core classes are designed to make data structure navigation and modification concise and easy-to-read.
GPath, in certain ways, is similar to XPath (http://www.w3.org/TR/xpath/) that is used for querying XML data. The main difference is that it uses dots instead of slashes to navigate the XML hierarchy and it can be used for navigating the hierarchy of objects (Plain Old Java
Objects (POJOs) and Plain Old Groovy Objects (POGOs) respectively).
The GPath syntax closely resembles E4X (ECMAScript for XML), which is an ECMAScript extension for accessing XML content.
This recipe will show how to parse an XML document and query its values and attributes through GPath.
Getting ready
As usual, we start by defining an XML snippet to test out our XML recipe. In this recipe,
we deal with movies. IMDB (Internet Movie Database) at http://www.imdb.com is the de facto standard for everything you want to know around the cinema universe. IMDB stores information about pretty much every movie ever made, along with actors and production data. IMDB is also a good citizen of the Internet and exposes API to retrieve the same data available on the site in XML. The API is not really documented, so we decide to roll out our own XML format based on the data we fetch from IMDB. Let's print the information about some movies having the word groovy in the title (admittedly not many!).
def groovyMoviez = '''<?xml version="1.0" ?> <movie-result>
<movie id="tt0116288"> <title>Groovy Days</title> <year>1996</year> <director>Peter Bay</director> <country>Denmark</country> <stars>
Ken Vedsegaard, Sofie Gråbøl,
175
www.it-ebooks.info

Working with XML in Groovy
Martin Brygmann</stars> </movie>
<movie id="tt1189088"> <title>Cool and Groovy</title> <year>1956</year> <director>Will Cowan</director> <country>USA</country> <stars>Anita Day,
Buddy De Franco and
Buddy DeFranco Quartet</stars> </movie>
<movie id="tt1492859">
<title>Groovy: The Colors of Pacita Abad</title> <year>2005</year>
<director>Milo Sogueco</director> <country>Philippines</country> <stars/>
</movie> </movie-result>
'''
How to do it...
Let's see how we can navigate the previous XML with GPath.
1.The first step is to process the XML using XmlSlurper so that we can access the GPath API:
def results = new XmlSlurper().parseText(groovyMoviez)
2.The rest is just Groovy's magic. The XML structure is magically converted into a navigable object structure based on the tags and attribute of the XML document:
for (flick in results.movie) {
println "Movie with id ${flick.@id} " + "is directed by ${flick.director}"
}
3.The code snippet yields the following output:
Movie with id tt0116288 is directed by Peter Bay Movie with id tt1189088 is directed by Will Cowan Movie with id tt1492859 is directed by Milo Sogueco
The code becomes extremely fluent and ceremony-free, just code and data.
176
www.it-ebooks.info

Chapter 5
4.Want to see something more awesome? Check out what we can do with the Groovy's spread-dot operator (*.):
results.movie*.title.each { println "- ${it}" } results.movie.findAll {
it.year.toInteger() > 1990 }*.title.each {
println "title: ${it}"
}
5.The output will be as follows: title: Groovy Days
title: Groovy: The Colors of Pacita Abad
6.Searching inside the XML document for specific content is also pretty simple:
results.movie.findAll { it.director.text().contains('Milo')
}.each {
println "- ${it.title}"
}
The findAll method is applied to the movie node and the closure passed to the findAll method checks for the presence of the word Milo in the director tag.
7.Should you need to search across all the nodes of the document (as opposed to a specific set of children, such as movie), it is possible to use the depthFirst method (or its shortcut **) on the root node:
results.'**'.findAll { it.director.text().contains('Milo')
}.each {
println "- ${it.title}"
}
8.The output will be as follows:
- Groovy: The Colors of Pacita Abad
How it works...
In the first step, we create a parser, an XmlSlurper in this case.
Please note how this time, we use the parseText method to read a string containing a valid XML document.
177
www.it-ebooks.info