Grails Cookbook - A collection of tutorials and examples

Groovy XmlSlurper Examples for Parsing XML

One common task in an enterprise application is parsing of XML documents. This task is commonly complicated in Java with lots of plumbing code, but is fairly easy and straightforward in Groovy. Below are examples on how to parse XML in Groovy using XmlSlurper. Visit this post if you wish to parse XML using XmlParser.

Simple XmlSlurper Example

Below is a simpler example on how to parse an XML information stored in a String:

package test
/**
 * A simple application that parses a String that contains XML information using XmlSlurper.
 */
class Test {
    static stringXML = '<person>'+
        '<firstName>John</firstName><lastName>Doe</lastName><age>25</age>'+
        '</person>'
    static main(args) {
        def person = new XmlSlurper().parseText(stringXML)
        println "first name: ${person.firstName}"
        println "last name: ${person.lastName}"
        println "age: ${person.age}"
    }
}

As shown in the example, there are no long plumbing code. We just need to instantiate an XmlSlurper and use it right away to parse an XML. The result is also straightforward as it will create an object that represent the hierarchical information of the XML document. We could get the information on the tags in the document by simply specifying them as properties. (E.g. <firstName> can be accessed as .firstName). Below is the output of the code when executed:
first name: John
last name: Doe
age: 25
As shown, the values are the same as specified in the XML.

Parse XML Attribute

If we wish to get the value of a tag's attribute, we can use the "@" symbol for that. Below is a simple example to illustrate this:
package test
/**
 * A Simple Example that parses an XML document and access an attribute using XmlSlurper
 */
class Test {
    static stringXML = '<person>'+
        '<firstName>John</firstName><lastName>Doe</lastName><age accurate="true">25</age>'+
        '</person>'
    static main(args) {
        def person = new XmlSlurper().parseText(stringXML)
        println "age: ${person.age}"
        println "accurate age: ${person.age.@accurate}"
    }
}
As shown in the sample XML, the age tag contains the attribute "accurate". To access this, the right notation is person.age.@accurate. The expected output is shown below:
age: 25
accurate age: true

Parse XML File

The samples above parses XML stored in String. But mostly, we are interested in parsing XML stored in files. For example, if we have the file "c:/temp/person.xml", with the following contents:
<person>
    <firstName>Jane</firstName>
    <lastName>Smith</lastName>
    <age>31</age>
</person>
The code to parse the file in Groovy using XmlSlurper is shown below:
package test
/**
 * A Simple example that parses an XML stored in a file using XmlSlurper.
 */
class Test {
    static main(args) {
        def person = new XmlSlurper().parse(new File("c:/temp/person.xml"))
        println "first name: ${person.firstName}"
        println "last name: ${person.lastName}"
        println "age: ${person.age}"
    }
}
As shown, the code is simple and self explanatory. The output is below:
first name: Jane
last name: Smith
age: 31

Parse XML Given URL

We can also use XmlSlurper to parse XML hosted on the web given a URL. We show an example of parsing a WSDL document available in this URL: http://www.webservicex.com/globalweather.asmx?WSDL

The contents looks something like below. Note that the actual document contains so much more information, but we just focus the fact that it contains message information.

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.webserviceX.NET" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://www.webserviceX.NET" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    ...
  </wsdl:types>
  <wsdl:message name="GetWeatherSoapIn">
    <wsdl:part name="parameters" element="tns:GetWeather" />
  </wsdl:message>
  <wsdl:message name="GetWeatherSoapOut">
    <wsdl:part name="parameters" element="tns:GetWeatherResponse" />
  </wsdl:message>
  <wsdl:message name="GetCitiesByCountrySoapIn">
    <wsdl:part name="parameters" element="tns:GetCitiesByCountry" />
  </wsdl:message>
  <wsdl:message name="GetCitiesByCountrySoapOut">
    <wsdl:part name="parameters" element="tns:GetCitiesByCountryResponse" />
  </wsdl:message>
  ...
</wsdl:definitions>
The code to retrieve and parse this XML using XmlSlurper is as simple as shown below:
package test
/**
 * A Simple Example that parses an XML from a Web Document.
 */
class Test {
    static main(args) {
        def wsdl = new XmlSlurper().parse("http://www.webservicex.com/globalweather.asmx?WSDL")
        wsdl.message.each { message ->
            println " message.name = "+message.@'name'	
            println "    part.name = " + message.part.@'name'
            println "    part.element = " + message.part.@'element'
        }
    }
}
As shown above, accessing the components are the same as the previous examples. We can access the values of tags similar to how we access properties, and we can get values of attributes using the @ symbol. The partial output is shown below:
 message.name = GetWeatherSoapIn
    part.name = parameters
    part.element = tns:GetWeather
 message.name = GetWeatherSoapOut
    part.name = parameters
    part.element = tns:GetWeatherResponse
 message.name = GetCitiesByCountrySoapIn
    part.name = parameters
    part.element = tns:GetCitiesByCountry
 message.name = GetCitiesByCountrySoapOut
    part.name = parameters
    part.element = tns:GetCitiesByCountryResponse
...
We can optionally provide the namespace information, which will yield similar output:
package test
/**
 * A Simple Example that parses an XML from a Web Document.
 */
class Test {
    static main(args) {
        def wsdl = new XmlSlurper().parse("http://www.webservicex.com/globalweather.asmx?WSDL")
            .declareNamespace(
                tm:"http://microsoft.com/wsdl/mime/textMatching/",
                soapenc:"http://schemas.xmlsoap.org/soap/encoding/",
                mime:"http://schemas.xmlsoap.org/wsdl/mime/",
                tns:"http://www.webserviceX.NET",
                soap:"http://schemas.xmlsoap.org/wsdl/soap/",
                s:"http://www.w3.org/2001/XMLSchema",
                soap12:"http://schemas.xmlsoap.org/wsdl/soap12/",
                http:"http://schemas.xmlsoap.org/wsdl/http/",
                wsdl:"http://schemas.xmlsoap.org/wsdl/")
        wsdl.message.each { message ->
            println " message.name = "+message.@'name'	
            println "    part.name = " + message.part.@'name'
            println "    part.element = " + message.part.@'element'
        }
    }
}

Searching Information from XML parsed by XmlSlurper

We can treat the object created by XmlSlurper as we treat other Objects created by Groovy. We can use findAll to search for multiple objects that meets a specified criteria. Below is an example that searches for all people with age greater than 20.
package test
/**
 * A Simple Example that searches information from XML parsed by XmlSlurper.
 */
class Test {
    static stringXML = 
        '<personDatabase>'+
        '  <person><firstName>John</firstName><lastName>Doe</lastName><age>25</age></person>'+
        '  <person><firstName>Jane</firstName><lastName>Smith</lastName><age>31</age></person>'+
        '  <person><firstName>Robert</firstName><lastName>Doe</lastName><age>11</age></person>'+
        '  <person><firstName>Michael</firstName><lastName>Smith</lastName><age>55</age></person>'+
        '  <person><firstName>Scott</firstName><lastName>Williams</lastName><age>35</age></person>'+
        '  <person><firstName>Alice</firstName><lastName>Anthony</lastName><age>14</age></person>'+
        '</personDatabase>'
    static main(args) {
        def people = new XmlSlurper().parseText(stringXML)
        people.person.findAll { p ->
            p.age.toInteger() > 20
        }.each { p ->
            println "${p.lastName}, ${p.firstName} is ${p.age} years old."
        }
    }
}
We can use findAll similar to how we use it with List. If you are new to how List are manipulated in Groovy, check this tutorial on Groovy List. The output is shown below.
Doe, John is 25 years old.
Smith, Jane is 31 years old.
Smith, Michael is 55 years old.
Williams, Scott is 35 years old.

Below is a slightly modified code that searches for all people whose surname starts with the letter "D".

package test
/**
 * A Simple Example that searches information from XML parsed by XmlSlurper.
 */
class Test {
    static stringXML = 
        '<personDatabase>'+
            '  <person><firstName>John</firstName><lastName>Doe</lastName><age>25</age></person>'+
            '  <person><firstName>Jane</firstName><lastName>Smith</lastName><age>31</age></person>'+
            '  <person><firstName>Robert</firstName><lastName>Doe</lastName><age>11</age></person>'+
            '  <person><firstName>Michael</firstName><lastName>Smith</lastName><age>55</age></person>'+
            '  <person><firstName>Scott</firstName><lastName>Williams</lastName><age>35</age></person>'+
            '  <person><firstName>Alice</firstName><lastName>Anthony</lastName><age>14</age></person>'+
        '</personDatabase>'
    static main(args) {
        def people = new XmlSlurper().parseText(stringXML)
        people.person.findAll { p ->
            p.lastName.toString().startsWith('D')
        }.each { p ->
            println "${p.lastName}, ${p.firstName}"
        }
    }
}

And the expected output is:
Doe, John
Doe, Robert
Posts about XML