-
Notifications
You must be signed in to change notification settings - Fork 155
Using XML
By default, HTTPBuilder classes will automatically parse XML responses using an XmlSlurper.
You can try the following example in the Groovy console (Groovy 1.6+ is needed for the @Grab macro):
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7')
import groovyx.net.http.HTTPBuilder
def http = new HTTPBuilder( 'http://api.openweathermap.org/data/2.5/' )
http.get( path: 'weather', query:[q: 'London', mode: 'xml'] ) { resp, xml ->
println resp.status
println "It is currently ${xml.weather.@value.text()} in London."
println "The temperature is ${xml.temperature.@value.text()} degrees Kelvin"
}
HTTPBuilder will automatically detect the content-type (assuming the sends the correct response header) and parse the response as XML. It is not necessary (but optional) to explicitly specify the contentType: ContentType.XML parameter.
HTML response data will also be parsed automatically, by using NekoHTML which corrects the XML stream before it is passed to the XmlSlurper. The resulting behavior is that you can parse HTML as if it was well-formed XML.
Keep in mind that particularly when parsing HTML documents, they often refer to external DTDs. The required behavior of all JAXP XML parsers is to retrieve and parse any referenced entities (e.g. DTD, schema, etc.) every time the document is processed (yes, even if validation is disabled.) This can become costly when the referenced entity document never changes.
To avoid the overhead of downloading and parsing externally referenced documents for every request, the HTTPBuilder's built-in XML and HTML parser uses an XML Catalog to store a local copy of frequently used DTD and entity definitions. You can add additional entity files to the default parser's catalog as well.
XML data is serialized using StreamingMarkupBuilder. You can define the body property as a closure like so:
http.request( POST, XML ) {
body = {
auth {
user 'Bob'
password 'pass'
}
}
}
The body is then transformed to an XML string by EncoderRegistry.encodeXML(). Alternatively, the XML body may be passed as a raw string as well.
Another common request is "What if I want to display the raw XML rather than parse it?"
In order to do that, you're going to send a contentType parameter, to force HTTPBuilder (or RESTClient) to use the TEXT parser. However, since setting the contentType also affects the Accept request header, we might need to override that as well.
For Example:
import groovyx.net.http.RESTClient
import static groovyx.net.http.ContentType.*
def weather = new RESTClient( 'http://api.openweathermap.org/data/2.5/' )
def resp = weather.get( path: 'weather', query:[q: 'London', mode: 'xml'], contentType: TEXT,
headers : [Accept : 'application/xml'] )
println resp.data.text // print the XML
Furthermore, you can use HTTPBuilder's defaults to reduce the number of parameters passed to each request method like so:
def weather = new RESTClient( 'http://api.openweathermap.org/data/2.5/' )
weather.contentType = TEXT
weather.headers = [Accept : 'application/xml']
def resp = weather.get( path: 'weather', query:[q: 'London', mode: 'xml'])