Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Include Page
GROOVY:XML Example
GROOVY:XML Example

Using Xalan

Here is an example of using XPath with Groovy to read an existing XML file:

Code Block
// require(groupId:'xalan', artifactId:'xalan', version:'2.6.0')
import org.apache.xpath.XPathAPI
import javax.xml.parsers.DocumentBuilderFactory

messages = []

def processCar(car) {
    def make = XPathAPI.eval(car, '@make').str()
    def country = XPathAPI.eval(car, 'country/text()').str()
    def type = XPathAPI.eval(car, 'record/@type').str()
    messages << make + ' of ' + country + ' has a ' + type + ' record'
}

def builder     = DocumentBuilderFactory.newInstance().newDocumentBuilder()
def inputStream = new ByteArrayInputStream(XmlExamples.CAR_RECORDS.bytes)
def records     = builder.parse(inputStream).documentElement

XPathAPI.selectNodeList(records, '//car').each{ processCar(it) }

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'
]

Using Jaxen

Here is an example of using Jaxen with Groovy to read an existing XML file:

Code Block

// require(groupId:'jaxen', artifactId:'jaxen', version:'1.1-beta-10')
import org.jaxen.dom.DOMXPath
import javax.xml.parsers.DocumentBuilderFactory

messages = []

def processCar(car) {
    def make = new DOMXPath('@make').stringValueOf(car)
    def country = new DOMXPath('country/text()').stringValueOf(car)
    def type = new DOMXPath('record/@type').stringValueOf(car)
    messages << make + ' of ' + country + ' has a ' + type + ' record'
}

def builder     = DocumentBuilderFactory.newInstance().newDocumentBuilder()
def inputStream = new ByteArrayInputStream(XmlExamples.CAR_RECORDS.bytes)
def records     = builder.parse(inputStream).documentElement

new DOMXPath('//car').selectNodes(records).each{ processCar(it) }

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'
]

Note: many libraries (e.g. DOM4J, JDOM, XOM) bundle or provide optional support for Jaxen. You may not need to download any additional JARs to use it.

Using Java's native XPath support

If you are using Java 5 and above, you don't need to use the standalone Xalan jar but instead can use the now built-in XPath facilities:

...

Code Block
def xml = '''
<doc>
  <person name="alan"><g>1</g><g>2</g><g>4</g></person>
  <person name="marc"><g>1</g><g>2</g><g>3</g></person>
  <person name="paul"><g>2</g><g>3</g><g>4</g></person>
  <person name="ivan"><g>2</g><g>4</g></person>
  <person name="eric"><g>4</g></person>
</doc>
'''

Using Java's native XPath support

Here is how to check that groups 2 and 4 are the groups in question using the built-in XPath capabilities of Java 5 and above:

...

Code Block
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.xpath.*

groupsOf = { name -> "/doc/person[@name='$name']/g" }
xpath    = "${groupsOf 'alan'}[.=${groupsOf 'paul'}][.=${groupsOf 'ivan'}]"
builder  = DocumentBuilderFactory.newInstance().newDocumentBuilder()
doc      = builder.parse(new ByteArrayInputStream(xml.bytes))
expr     = XPathFactory.newInstance().newXPath().compile(xpath)
nodes    = expr.evaluate(doc, XPathConstants.NODESET)
assert   nodes.collect { node -> node.textContent } == ['2', '4']

Using GPath

Of course, you can also do this without XPath by using Groovy's GPath facilities as follows:

...