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.