Versions Compared


  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

This example assumes the following class is already on your CLASSPATH:

Include Page
XML Example
XML Example

Here is an example of using XmlSlurper:

Code Block
def records = new XmlSlurper().parseText(XmlExamples.CAR_RECORDS)
def allRecords =
assert 3 == allRecords.size()
def allNodes = records.depthFirst().collect{ it }
assert 10 == allNodes.size()
def firstRecord =[0]
assert 'car' ==
assert 'Holden' == firstRecord.@make.text()
assert 'Australia' ==
def carsWith_e_InMake ={ it.@make.text().contains('e') }
assert carsWith_e_InMake.size() == 2
// alternative way to find cars with 'e' in make
assert 2 =={ it.@make =~ '.*e.*' }.size()
// makes of cars that have an 's' followed by an 'a' in the country
assert ['Holden', 'Peel'] =={ =~ '.*s.*a.*' }.@make.collect{ it.text() }
def expectedRecordTypes = ['speed', 'size', 'price']
assert expectedRecordTypes == records.depthFirst().grep{ it.@type != '' }.'@type'*.text()
assert expectedRecordTypes == records.'**'.grep{ it.@type != '' }.'@type'*.text()
def countryOne =[1].country
assert 'Peel' == countryOne.parent().@make.text()
assert 'Peel' == countryOne.'..'.@make.text()
// names of cars with records sorted by year
def sortedNames ={ it.@year.toInteger() }.'@name'*.text()
assert ['Royale', 'P50', 'HSV Maloo'] == sortedNames
assert ['Australia', 'Isle of Man'] == records.'**'.grep{ it.@type =~ 's.*' }*.parent().country*.text()
assert 'co-re-co-re-co-re' =={[0..1] }.join('-')
assert 'co-re-co-re-co-re' =='*'.collect{[0..1] }.join('-')


  • If your elements contain characters such as dashes, you can enclose the element name in double quotes. Meaning for:
Code Block
  • You do the following:
    Code Block
    def foo = new XmlSlurper().parseText(FOO_XML)
    assert "test" == foo."foo-bar".text()

You can also parse XML documents using namespaces:

Code Block
def wsdl = '''
<definitions name="AgencyManagementService"
    <ns1:message name="SomeRequest">
        <ns1:part name="parameters" element="SomeReq" />
    <ns2:message name="SomeRequest">
        <ns2:part name="parameters" element="SomeReq" />

def xml = new XmlSlurper().parseText(wsdl).declareNamespace(ns1: '', ns2: '')
println xml.'ns1:message'.'ns1:part'.size()
println xml.'ns2:message'.'ns2:part'.size()

XmlSlurper has a declareNamespace method which takes a Map of prefix to URI mappings. You declare the namespaces and just use the prefixes in the GPath expression.

Code Block
new XmlSlurper().parseText(blog).declareNamespace(dc: "").channel.item.findAll { item ->
   d.any{entry -> item."dc:date".text() =~ entry.key} && a.any{entry -> item.tags.text() =~ entry

Some remarks:

  • name or "*:name" matches an element named "name" irrespective of the namespace it's in (i.e. this is the default mode of operation)
  • ":name" matches an element named "name" only id the element is not in a namespace
  • "prefix:name" matches an element names "name" only if it is in the namespace identified by the prefix "prefix" (and the prefix to namespace mapping was defined by a previous call to declareNamespace)

You can generate namespaced elements in StreamingMarkupBuilder very easily:

Code Block
System.out << new StreamingMarkupBuilder().bind {
    mkp.declareNamespace(dc: "")

    root {