Android XML Binding with Simple Framework Tutorial
In the past, I showed you how to parse XML using the SAX approach and how to boost your Android XML parsing with XML Pull. Both these techniques work, but are rather boring since they qualify as “plumbing code”. In this tutorial I am going to show you how to perform XML binding in Android using the Simple framework.
XML data binding is quite popular in Java and there are multiple frameworks that allow binding. Solutions like JAXB and XStream are well established and heavily used. However, these libraries come with a large footprint, something that makes them inappropriate for use in the resources constraint world of mobiles. The good news is that there is a new kid on the block, the Simple framework. As its name implies, it strives to bring some simplicity in the bloated world of XML.
From the official Simple framework site:
Simple is a high performance XML serialization and configuration framework for Java. Its goal is to provide an XML framework that enables rapid development of XML configuration and communication systems. This framework aids the development of XML systems with minimal effort and reduced errors. It offers full object serialization and deserialization, maintaining each reference encountered.
Very nice. You can get started with the framework by visiting the documentation page and you should also read how does JAXB compare to Simple. Simple could change the way you handle XML in your Java applications, give it a try.
The big question is whether Simple is supported in Android’s JVM. Android uses Dalvik, a specialized virtual machine optimized for mobile devices. Additionally, Dalvik use a subset of Apache’s Harmony project for the core of its Class Library. Not all Java core classes are supported. For example, some of the javax.xml.* subpackages are not included.
Well, Simple CAN work with Android. More specifically, I managed to use version 2.3.2 which can be found in Simple’s download page. The corresponding JAR has a size of 287KB. The release notes for that version mention:
- Addition of DOM provider so that StAX is not a required dependency
- Fix made to ensure property defaults are applied correctly to classes
The first issue is very important because the StAX API is not included in Android’s SDK. Note that the latest versions of Simple (after v2.3.2) also work and can be used for our purposes.
Let’s cut to the chase and see how to perform the binding. As an example I will use an XML document that is returned as a response from the TMDb API which I use in the sample full Android application I build. Here is the document:
Movies search for “Transformers” and (year) “2007”
The response example can also be found here.
First of all download Simple version 2.3.2 and include it in your project’s classpath. Then take a quick look at the Simple framework Javadocs.
The most important thing is to create our model objects and map the appropriately to the XML formatted document. If we take a look at the XML file, we shall see that the root element is called OpenSearchDescription and it includes a Query element, a “totalResults” element and a number of movies. Here how our main model class looks like:
package com.javacodegeeks.xml.bind.model; import java.util.List; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.Root; @Root public class OpenSearchDescription { @Element(name="Query") public Query query; @Element public int totalResults; @ElementList public List<Movie> movies; }
The Root annotation denotes that the specific class represents a root XML element. We also use the Element and ElementList annotations for the nested elements. Note that Simple can handle both “getters/setters” and “public fields” approaches. I use the latter in this example. One thing to be aware of is that we use the name field (for “Query”) in order to provide the corresponding XML element name. This should be done when the XML element has a different name than the Java field, since Simple by default looks for an element with the same name as the field.
Let’s now see the Query class:
package com.javacodegeeks.xml.bind.model; import org.simpleframework.xml.Attribute; import org.simpleframework.xml.Element; @Element public class Query { @Attribute public String searchTerms; }
This class contains only an attribute called “searchTerms” so the relevant field is annotated with Attribute.
Very easy until now. Let’s check the Movie class:
package com.javacodegeeks.xml.bind.model; import java.util.List; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementList; @Element(name="movie") public class Movie { @Element(required=false) public String score; @Element(required=false) public String popularity; @Element(required=false) public String name; @Element(required=false) public String id; @Element(required=false) public String biography; @Element(required=false) public String url; @Element(required=false) public String version; @Element(required=false) public String lastModifiedAt; @ElementList public List<Image> images; }
The only new thing is that the required field is used in order to declare that a field is not required (can be null). This is done because some fields are empty in the API response.
Let’s see the Image class:
package com.javacodegeeks.xml.bind.model; import org.simpleframework.xml.Attribute; import org.simpleframework.xml.Element; @Element(name="image") public class Image { @Attribute public String type; @Attribute public String url; @Attribute public String size; @Attribute public int width; @Attribute public int height; @Attribute public String id; }
This class includes only attributes so we annotate the fields accordingly.
The final step is to read the source XML and let Simple wire all the classes and populate the fields. This is done by using the Persister class which provides an implementation for the Serializer interface. We shall use its read method which reads the contents of the XML document from a provided source and convert it into an object of the specified type. Note that we have disabled the strict mode. Here is how it looks inside an Android Activity:
package com.javacodegeeks.xml.bind; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.simpleframework.xml.Serializer; import org.simpleframework.xml.core.Persister; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import com.javacodegeeks.xml.bind.model.OpenSearchDescription; public class SimpleExampleActivity extends Activity { private static final String url = "http://dl.dropbox.com/u/7215751/JavaCodeGeeks/AndroidFullAppTutorialPart03/Transformers+2007.xml"; private DefaultHttpClient client = new DefaultHttpClient(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { String xmlData = retrieve(url); Serializer serializer = new Persister(); Reader reader = new StringReader(xmlData); OpenSearchDescription osd = serializer.read(OpenSearchDescription.class, reader, false); Log.d(SimpleExampleActivity.class.getSimpleName(), osd.toString()); } catch (Exception e) { Toast.makeText(this, "Error Occured", Toast.LENGTH_LONG).show(); } } public String retrieve(String url) { HttpGet getRequest = new HttpGet(url); try { HttpResponse getResponse = client.execute(getRequest); final int statusCode = getResponse.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { return null; } HttpEntity getResponseEntity = getResponse.getEntity(); if (getResponseEntity != null) { return EntityUtils.toString(getResponseEntity); } } catch (IOException e) { getRequest.abort(); Log.w(getClass().getSimpleName(), "Error for URL " + url, e); } return null; } }
This is a typical Android Activity. We retrieve the XML document as an internet resource (check my tutorial on how to use the HTTP API) and then create a StringReader from the response. We feed the Serializer with that and then let Simple perform its magic and return as a full class with the appropriate fields and embedded classes all populated. The specific app will just dump the classes string representations to the system’s log, which can be monitored in the DDMS view.
That’s all guys. No more manual XML parsing for me. As always, you can download the Eclipse project created for this tutorial.
Happy Android coding! And don’t forget to share!
Related Articles:
05-18 12:05:35.832: W/System.err(930): org.simpleframework.xml.stream.NodeException: Document has no root element
Great tutorial, and thanks a lot. Please, I have a question. If I want to post from my android app the same data to be stored in an external database using the web service, how do I do this?
Job well done!
Although SimpleXml can work on Android, it’s still a little heavy-weight for resource limited mobile device, anyway, SimpleXml originally was not designed with Android in mind.
I’ve built a light-weight xml binding framework tailored for Android platform, its called Nano, and I have adapted the author’s original movie search full android application to use Nano binding instead, if you are interested, you can find Nano and the full adapted movie search application by following links below:
https://github.com/bulldog2011/nano
http://bulldog2011.github.com/blog/2013/02/12/movie-search-android-app-using-nano/
how can i read xml from assets folder ?
>> XML is still important in the area of web services even though REST has gained significant attention lately.
REST does not imply JSON. You can have a REST API using XML.