Groovy tiene varias formas de manipular XML. Veremos el uso de XmlSlurper, una clase que nos permite parsear un XML de manera muy simple y rápida.

El XML

El XML que leeremos será el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<personas>
 <persona edad="159">
 <id>10</id>
 <nombre>Invasor Zim</nombre>
 <origen>Irken</origen>
 </persona>
 <persona edad="14">
 <id>20</id>
 <nombre>Dib</nombre>
 <origen>Tierra</origen>
 </persona>
 <persona edad="12">
 <id>30</id>
 <nombre>Gaz</nombre>
 <origen>Tierra</origen>
 </persona>
</personas>

Uso del XmlSlurper

El primer paso es contruir un objeto XmlSlurper, el cual representará en memoria al XML. De esta manera podremos acceder a los nodos del XML de muchas formas convenientes. Para parsear el XML escribimos:

def personas = new XmlSlurper().parse(new File("personas.xml"))

¡Y listo! A partir de ahora podemos usar el objeto personas para acceder al XML.

El objeto personas tiene una representación interna de los nodos a partir de los nombres de los tags. Así, por ejemplo, podemos imprimir todos los nombres de las personas:

personas.persona.nombre.each( { println it })

En este caso, personas.persona representa a todos los nodos cuyo tag es "persona"; a su vez, personas.persona.nombre representa a todos los nodos "nombre" de cada nodo "persona".

También podemos acceder a un nodo en particular:

personas.persona[2].nombre

Acceder a los nodos sin saber su nombre

También podemos acceder al nombre de un tag si no lo conocemos:

personas.name() //devuelve "personas"

O imprimir todos los datos de cada persona:

personas.children().each( { it.children().each( { println it }) } )

En el ejemplo anterior recorremos todos los nodos "hijo" del tag padre "personas" (es decir, los nodos persona), y por cada nodo persona recorremos todos sus nodos hijos y los imprimimos.

Restringir resultados con findAll()

Por último, algo muy útil es utilizar el método findAll() para restringir una colección. Por ejemplo, si quisieramos imprimir todos los nombres de las personas cuyo id sea mayor a 10:

grupoRestringido = personas.persona.findAll( { it.id.toInteger() > 10 })
grupoRestringido.each( { println it.nombre} )

O lo mismo, de manera un poco más abreviada:

personas.persona.findAll( { it.id.toInteger() > 10 }).each( { println it.nombre} )

Acceder a los atributos

Podemos acceder a los atributos de los nodos (el atributo "edad") usando la siguiente notación:

edad = personas.persona[0].'@edad'

En este ejemplo la variable edad contendrá el valor 159 (la edad de Zim).

Con lo que ya sabemos, podemos imprimir la edad de todas las personas:

personas.persona.'@edad'.each( {println it } )

O un poquito más complejo, escribir los nombres y las edades de todas las personas:

personas.persona.each( { println "La edad de ${it.nombre} es ${it.'@edad'}" })