Skip to: Site menu | Main content

Groovy 

      Download | Documentation | Developers | Community

An agile dynamic language for the Java Platform

Reading XML using Groovy's DOMCategory Add comment to Wiki View in Wiki Edit Wiki page Printable Version

Information

Java has in-built support for DOM processing of XML using classes representing the various parts of XML documents, e.g. Document, Element, NodeList, Attr etc. For more information about these classes, refer to the respective JavaDocs. Some of the key classes are:

DOM class JavaDocs
Element 1.4 5
NodeList 1.4 5

Groovy syntax benefits can be applied when using these classes resulting in code which is similar to but more compact than the Java equivalent. In addition, Groovy supports the following built-in helper method for these classes.

DOM class Method Description/Equivalent longhand
NodeList .iterator() same as for loop, enables closures, e.g. findAll, every, etc.

In addition, the DOMCategory class provides numerous additional helper methods and syntax shortcuts:

DOM class Method Description/Equivalent longhand
Element .'child' or .child or ['child'] similar to .getElementsByTagName('child') but only gets direct children
Element .children() or .'*' or ['*'] special case of above which finds all children regardless of tagname (plus text nodes)
Element .'@attr' or ['@attr'] .getAttribute('attr')
Element .attributes() equivalent to .attributes returns a NamedNodeMap
Element .text() .firstChild.nodeValue (or textContent if you are using Xerces)
Element .name() .nodeName
Element .parent() or .'..' or ['..'] .parentNode
Element .depthFirst() or .'**' depth-first traversal of nested children
Element .breadthFirst() breadth-first traversal of nested children
Node .toString() text node value as a String
NodeList .size() .length
NodeList .list() converted to a list of nodes
NodeList [n] .item(n)
NodeList .text() .collect{ it.text() }
NodeList .child flattened version of .child for each node in the NodeList
NamedNodeMap .size() .length
NamedNodeMap .'child' or .child or ['child'] .getNamedItem(elementName).nodeValue

All these methods return standard Java classes (e.g. String and List) or standard DOM classes (e.g. Element, NodeList), so there are no new classes to learn, just some improved syntax.

Example

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

XmlExamples.groovy
class XmlExamples {
  static def CAR_RECORDS = '''
    <records>
      <car name='HSV Maloo' make='Holden' year='2006'>
        <country>Australia</country>
        <record type='speed'>Production Pickup Truck with speed of 271kph</record>
      </car>
      <car name='P50' make='Peel' year='1962'>
        <country>Isle of Man</country>
        <record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg in weight</record>
      </car>
      <car name='Royale' make='Bugatti' year='1931'>
        <country>France</country>
        <record type='price'>Most Valuable Car at $15 million</record>
      </car>
    </records>
  '''
}

Here is an example of using Groovy's DOMCategory:

import groovy.xml.DOMBuilder
import groovy.xml.dom.DOMCategory

messages = []

def processCar(car) {
    assert car.name() == 'car'
    def make = car.'@make'
    def country = car.country[0].text()
    def type = car.record[0].'@type'
    messages << make + ' of ' + country + ' has a ' + type + ' record'
}

def reader  = new StringReader(XmlExamples.CAR_RECORDS)
def doc     = DOMBuilder.parse(reader)
def records = doc.documentElement

use (DOMCategory) {
    assert 9 == records.'*'.size()
    def cars = records.'car'
    assert cars[0].parent() == records
    assert 3 == cars.size()
    assert 2 == cars.findAll{ it.'@year'.toInteger() > 1950 }.size()
    def carsByCentury = cars.list().groupBy{
        it.'@year'.toInteger() >= 2000 ? 'this century' : 'last century'
    }
    assert 1 == carsByCentury['this century'].size()
    assert 2 == carsByCentury['last century'].size()
    cars.each{ car -> processCar(car) }
}

assert messages == [
    'Holden of Australia has a speed record',
    'Peel of Isle of Man has a size record',
    'Bugatti of France has a price record'
]