Friday, September 18, 2009

Pretty-printing XML results returned from Groovy RESTClient

In another blog post here, someone commented that they had to fall back to HTTPBuilder to output the XML returned from a REST request because RESTClient automatically parses the XML and returns a GPathResult NodeChild object. That's certainly one solution (and it gives you a good amount of control over both the request and its output), but if you *really* want to use RESTClient, it's still possible to format the results parsed via XMLSlurper.

When I needed to do this, I ended up using a combination of Groovy's StreamingMarkupBuilder to create the initial output, then I used Xalan to transform that output into easier to read XML. The method ended up looking like this:

import groovy.xml.StreamingMarkupBuilder

import javax.xml.transform.TransformerFactory
import javax.xml.transform.Transformer
import javax.xml.transform.OutputKeys
import javax.xml.transform.stream.StreamResult
import javax.xml.transform.stream.StreamSource

/**
* pretty prints the GPathResult NodeChild
*/
def outputFormattedXml(node) {
def xml = new StreamingMarkupBuilder().bind {
mkp.declareNamespace("":node.namespaceURI())
mkp.yield(node)
}

def factory = TransformerFactory.newInstance()
def transformer = factory.newTransformer()
transformer.setOutputProperty(OutputKeys.INDENT, 'yes')

// figured this out by looking at Xalan's serializer.jar
// org/apache/xml/serializer/output_xml.properties
transformer.setOutputProperty("{http\u003a//xml.apache.org/xalan}indent-amount", "2")
def result = new StreamResult(new StringWriter())
transformer.transform(new StreamSource(new ByteArrayInputStream(xml.toString().bytes)), result)

return result.writer.toString()
}


As I mentioned in the code comments, there were some pieces I had to figure out from looking in Xalan's serializer.jar. For modifying other output properties, take a look at org/apache/xml/serializer/output_xml.properties in serializer.jar to see just what you can customize and how to refer to it in your code.

In the end, the above method could probably be used to pretty-print any NodeChild object from GPathResult. There may be an easier or "more Groovy" way to output this kind of thing, but this allows the use of both the easy-to-use RESTClient and the easy-to-use XmlSlurper without having to worry much about making the output human-readable.

5 comments:

Mike Miller said...

Dude,

You stole my thunder - that was going to be my next blog...

I wrote a test tool for testing one of our RESTful web services and wanted to display the inbound request xml and the resulting xml.

Maybe now I don't need to...

Jeffrey Erikson said...

Sorry ;) It certainly wouldn't hurt to see another way to solve the problem, though, so feel free to post.

Mike Miller said...

I agree. I will probably go ahead and post my code which shows the call going thru HTTPBuilder and displays the input and output XML.

Jeffrey Erikson said...

Feel free to link to it here when you do . . . would definitely be interesting to see.

phil varner said...

Thanks, this helped a lot!