Combining Groovy and XSLT for Data Transformation

In the blog post Beautiful Transformations with Groovy I described how easy it is to create data transformations with Groovy. But sometimes organisations invested massively in XSLT transformation and want to reuse their existing XSLT templates. Read on for an an example that shows how to do that.

Assume we want to transform the following XML file to HTML:


  
    Germany
    Fast and nice
  
  
    Spain
    Large and handy
  
  
    Italy
    Small and cheap
  

Lets further assume the result should look like this:

Does it make sense? I don’t know, but that’s not really important. 😉

We have the following XSLT template to perform the transformation:

All you need is a Groovy script like the one below to transform the xml file to html using the given xslt.

// Load xslt
def xslt= new File("template.xsl").getText()

// Create transformer
def transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(new StringReader(xslt)))

// Load xml
def xml= new File("cars.xml").getText()

// Set output file
def html = new FileOutputStream("output.html")

// Perform transformation
transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(html))

This is self-explanatory, isn’t it?
As XSLT is somewhat limited when it comes to more complex transformations, it can be extended by custom processors which can we implemented in Java or Groovy. A custom processor in Groovy can be implemented like this:

public class AgeProcessor{
    public def process(ExpressionContext context,int n){
        return "Age: " + (2012 - n) + " years";
    }
}

The processor is hooked up to the XSLT using the expressions in line 3 and 28 of the above XSLT file.
The examples above show how to reuse existing XSLT in Groovy. Are you interested to see the same same transformation in pure Groovy? (sorry, I could not resist ;-))
Here is the code:

// Load xml
def cars = new XmlSlurper().parse(new File("cars.xml"))

// Set output file
def writer = new FileWriter("output.html")

// Perform transformation
def builder = new MarkupBuilder (writer);
builder.html(xmlns:"http://www.w3.org/1999/xhtml") {
    head {
        title "Cars collection"
    }
    body {
        h1("Cars")
        ul(){
            cars.car.each{car ->
                li(car.@name.toString() + "," + car.country + "," + car.description + ", Age: " + (2012 - car.@year.toInteger()) + " years")
            }
        }
    }
 }

It is shorter and self-contained. It is also more intuitive and therefore easier to maintain. But if you have the requirement to support XSLT in Groovy you now know how to do that.

Trapped in the Comfort Zone

Many agile techniques such as Kaizen, Sashimi or Kanban correspond to terms and principles found in asian culture. A less known principle is:

“Do not develop an attachment to any one weapon or any one school of fighting”
– Miyamoto Musashi

In the context of agile it means that one should change the process if it helps to achieve the goals. This is something most developers would agree to as processes are often seen as impediments.
The same applies to technology. Translated to the technical world it reads: Do not stick to your favourite technology if there is something better suited to meet the project or customer needs. This is something many developers would not immediately agree to. Developers usually love sticking to their JEE, Spring, .NET, SOAP, REST, [any other technology] with which they grew up. They often argue that learning a new technology is time consuming and therefore hardly possible to change.
I think that is wrong. Provided a developer has a sound background, he or she can become productive in a new technology within a short time. I’ve seen developers switching from JEE to .NET and vice versa without problems. This is possible because technology always evolves. Most new frameworks and programming languages do not reinvent the wheel. The are always based on similar common principles which remain valid and stable over time. It is more a matter of mindset that keeps people trapped in their technology comfort zone.

Is that a problem?

Sometimes yes, especially when paired with Groupthink, it hinders innovation and production efficiency.

How can this prevented?

1. Make sure you have people with long standing experience in different technology domains in your team. People who worked with multiple technologies are usually more willing to reflect technology decisions and align them to the requirements of the business.

2. Don’t start a project with a strong technology committment. Let the team decide which technology is best suited to solve the business problem. Of course in conformance with the corporate standards.

3. Ensure that the team has the freedom to decide which tools they want to use.

Having the option to change weapons (processes, tools, frameworks, etc.) if needed, improves the likeliness of successful project delivery.