XML Handling in Scala

It is finally time to get back to Scala. In this post, lets cover briefly some of the support Scala has for handling XML data. This is impressive stuff, and more so if you are used to how complex this can be in Java, for example.

Lets start with a simple example. Lets imagine you are dealing with a legacy system that exposes user information in an XML file like this excerpt:

<users>
  <user>
    <name>Paulo</name>
    <country>Brasil</country>
    <website>http://www.jcranky.com</website>
  </user>
</users>

In Java it would take you a lot of code and some patience to get this file transformed into an entity object. At the very least, you would need to find some library and/or configure some kind of mapping. Now this is how you can do it in Scala:

// define the User entity class
case class User (name: String, country: String, website: String)

// create a new User instance, using the xml data
val user = new User((userXml  "name").text, (userXml  "country").text, (userXml  "website").text)

The case keyword above says that the User class is a bean – i.e. Scala will generate getters and setters for you, you will have a nice “toString” implementation, among other things.

If you want to try it yourself you can simply type the xml data in the scala interpreter and attribute it to a variable or constant, like the code bellow, and then use to code above to process it:

val userXml =
<users>
  <user>
    <name>Paulo</name>
    <country>Brasil</country>
    <website>http://www.jcranky.com</website>
  </user>
</users>

The only additional thing you have to do in order to allow Scala to understand the xml code is to add this import statement:

import scala.xml._

There are  two things happening in the xml handling above. First, userXml “name” gets a NodeSeq for each name tag found. Then text gets the String representing the tag’s body, which can be passed to the User’s constructor.

Now, something is wrong here, right? If I left the code in the example as is, I will only be able to read ONE user! Ok, I hear you. Just add a foreach loop, like bellow, and you’re done:

// extract the user reading code to a function
def readUser(userXml: NodeSeq): User = {
  new User((userXml  "name").text, (userXml  "country").text, (userXml  "website").text)
}

// loop through all users found in the xml and print them
usersXml.foreach(userXml => println(readUser(userXml)))

Better now? =)

Do you see that foreach thing we used in the last example? Well, that is not a XML specific function. It is defined in the Scala Collection API. Since the XML support is built on top of the Scala Collection API, you can do to xml everything you do to collections.

In this example, I’m demonstrating very basic features. There is a lot more worth taking a look in the Scala xml libraries. We only covered xml reading, for example. Writing may come in another post =)

Advertisements
This entry was posted in scala and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s