Tuesday, February 24, 2009

Processing XML in Groovy

Working with XML in Groovy is a real pleasure when compared with more traditional statically typed languages (Java, C#). Groovy provides a couple of different mechanisms for processing XML but for this post I’ll focus on the XMLSlurper class. To illustrate how simple it is to consume XML let’s look at a simple example XML stream:

   1: <customer>
   2:     <firstName>Joe</firstName>
   3:     <address>
   4:         <addressLine1>1111 Test Address Way</addressLine1>
   5:         <addressLine2>co test address</addressLine2>
   6:         <city>Columbus</city>
   7:         <state>TN</state>
   8:         <postalCode>22333</postalCode>
   9:     </address>
  10:     <address>
  11:         <addressLine1>2222 Test Address Street</addressLine1>
  12:         <addressLine2></addressLine2>
  13:         <city>Centerville</city>
  14:         <state>TX</state>
  15:         <postalCode>33444</postalCode>
  16:     </address>
  17:     <address>
  18:         <addressLine1>3333 Yet Another Address Avenue</addressLine1>
  19:         <addressLine2>Suite 222</addressLine2>
  20:         <city>Salem</city>
  21:         <state>VA</state>
  22:         <postalCode>44555</postalCode>
  23:     </address>
  24: </customer>

For the first example, we’ll simply assign a string variable equal to this multi line string field (In groovy the way to indicate a multi line string is to use the triple quote symbol). Once we’ve assigned the xml to a string we’ll consume the xml elements and print them to the console.

   1: def customerXMLData = 
   2:     """<customer>
   3:             <firstName>Joe</firstName>
   4:             <address>
   5:                 <addressLine1>1111 Test Address Way</addressLine1>
   6:                 <addressLine2>co test address</addressLine2>
   7:                 <city>Columbus</city>
   8:                 <state>TN</state>
   9:                 <postalCode>22333</postalCode>
  10:             </address>
  11:             <address>
  12:                 <addressLine1>2222 Test Address Street</addressLine1>
  13:                 <addressLine2></addressLine2>
  14:                 <city>Centerville</city>
  15:                 <state>TX</state>
  16:                 <postalCode>33444</postalCode>
  17:             </address>
  18:             <address>
  19:                 <addressLine1>3333 Yet Another Address Avenue</addressLine1>
  20:                 <addressLine2>Suite 222</addressLine2>
  21:                 <city>Salem</city>
  22:                 <state>VA</state>
  23:                 <postalCode>44555</postalCode>
  24:             </address>
  25:         </customer>"""
  26: def customerXML = new XmlSlurper().parseText(customerXMLData)
  27:  
  28: println("Customer's first name: " + customerXML.firstName)
  29: customerXML.address.each{address ->
  30:     println("Address:")
  31:     println("     address line 1: " + address.addressLine1)
  32:     println("     address line 2: " + address.addressLine2)
  33:     println("               City: " + address.city)
  34:     println("              State: " + address.state)
  35:     println("        Postal Code: " + address.postalCode)

To expand on this a bit further, we can now move the xml into an external text file. With a very simple change to our test code we can process this same xml from a file instead as the following example illustrates.

   1: def customerXMLData = new File("D:\\temp\\Customer.xml")
   2: def customerXML = new XmlSlurper().parse(customerXMLData)
   3:  
   4: println("Customer's first name: " + customerXML.firstName)
   5: customerXML.address.each{address ->
   6:     println("Address:")
   7:     println("     address line 1: " + address.addressLine1)
   8:     println("     address line 2: " + address.addressLine2)
   9:     println("               City: " + address.city)
  10:     println("              State: " + address.state)
  11:     println("        Postal Code: " + address.postalCode)

Note how simple it is to read the data from a file. If you were writing this code for a production environment, you would likely want to wrap the new File instance in a try catch block and catch the file not found exception and handle it gracefully. One of the benefits of Groovy over Java is that it allows you to decide whether or not you want to deal with these exceptions (if the file you’re reading is the web.xml file for example it’s probably safe to assume it’s always there in a production site and may not warrant the extra try/catch block. The other difference to point out in this last example is the method on line 2 changed from ‘parseText’ to simply ‘parse’. parseText is meant to work specifically with strings where parse is much more flexible and can work with a url or a file.

3 comments:

  1. thank you sir, this is a simple example and easy to understand for a newbie like me :)

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Hi Sir,
    I'm new to Groovy.
    Can you please tell me, how to create a XML file and append some set of nodes on that XML file. .
    How to parsing XML file and append node.
    Give some examples. .
    Thanks in advance. . .

    ReplyDelete