Android SDK: Build a Simple SAX Parser

Android SDK: Build a Simple SAX Parser

Tutorial Details
  • Technology: Android SDK
  • Difficulty: Intermediate
  • Completion Time: 30 - 60 Minutes

Parsing data from an XML file is a very common goal in mobile applications. This tutorial will provide you with a hands on approach for reading XML data with a SAX parser. SAX is an abbreviation for “Simple API for XML”, and it is a very powerful tool for reading XML.


SAX Parser Pros and Cons

One of the biggest advantages that SAX parsers offer is a low memory footprint. They parse each line of XML data at a time and consequently do not need to load the entire XML document into memory prior to making the data accessible. This is a significant boost to performance, and this really becomes visible when working with large XML documents.

One of the disadvantages of using a SAX parser is that you must define an event-driven API that will respond to each element as it is received. This can become time consuming to build, but if you are willing to spend a little extra time to get it right, the outcome will be worthwhile.


Understanding XML

XML is a means of storing and transporting data. One of the main things you will need to know for this tutorial is the structure of an XML document. XML is made from a series of tags, just like HTML. An example of am opening tag would be <example>, and a complementary closing tag would be </example>. Between these tags we will find the data contained by the example tag (also called an element). In certain cases, we may have tags with attributes that we need to handle in our SAX parser. An example of this occurring in XML would be <example attr='value'>.


Step 1: Setting Up the Application

You will need to create a new project in Eclipse. Since we are working with XML and will be making use of the Internet for data transfer, we need to give the application permission to access the Internet. To do this you need to open the application’s manifest file and add this line of code at the bottom, just before the closing </manifest> tag:

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

While you are in your manifest file you should also make your application debuggable. This can be done by adding the following line of code in your application tag:

android:debuggable='true'

Now that the application has access to the Internet and is debuggable, we can begin implementing the SAX parser.


Step 2: Creating Classes and UI

First, you will need to create three classes. The first class that should be created when you created the project will be your activity. In this activity, all the data retrieved will be used and displayed to the screen. The second class required will be the handler, in this class all the extracting and setting of data will be done. The third class will contain all the getters and setters that we need to set the data and retrieve it.

The main.xml in your resource folder should be modified as shown below:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:id="@+id/layout">
    <TextView
        	android:layout_width="fill_parent"
        	android:layout_height="wrap_content"
        	android:text="@string/hello"
        	android:textSize="15dp"
android:gravity="center_horizontal"
        	android:id="@+id/layout_string"/>
</LinearLayout>

Step 3: The Content Handler

The content handler is where we need to handle each of the incoming events from the XML. So, basically what the content handler will do is read through the XML until it reaches the end.

When an opening tag such as <example> is reached, the startElement handler will be called. When closing tags such as </example> is reached, a closing method called endElement gets called. When the SAX parser reaches the closing tags, it calls a method called characters which will get all the content that is between the opening and closing tags.
We have a String that is called elementValue, which is set to null. Each time the parser goes through to start an end tag, we will set the elementValue string to the data in between those tags.
We will also make use of a Boolean value called elementOn. We use this to keep track of where the XML is being passed, so that when a tag is finished being read and data has been extracted, we set it to false so that we can read the next tag in the XML.

We have if statements to check when we reach a specific tag in order to use setters to set the data to an array list, so that we can display it later.

Below is the sample code used in the content handler:

package com.android.SAXParser;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XMLHandler extends DefaultHandler {
	String elementValue = null;
	Boolean elementOn = false;
	public static XMLGettersSetters data = null;
	public static XMLGettersSetters getXMLData() {
		return data;
	}
	public static void setXMLData(XMLGettersSetters data) {
		XMLHandler.data = data;
	}
	/**
	 * This will be called when the tags of the XML starts.
	 **/
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		elementOn = true;
		if (localName.equals("CATALOG"))
		{
			data = new XMLGettersSetters();
		} else if (localName.equals("CD")) {
			/**
			 * We can get the values of attributes for eg. if the CD tag had an attribute( <CD attr= "band">Akon</CD> )
			 * we can get the value "band". Below is an example of how to achieve this.
			 *
			 * String attributeValue = attributes.getValue("attr");
			 * data.setAttribute(attributeValue);
			 *
			 * */
		}
	}
	/**
	 * This will be called when the tags of the XML end.
	 **/
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		elementOn = false;
		/**
		 * Sets the values after retrieving the values from the XML tags
		 * */
		if (localName.equalsIgnoreCase("title"))
			data.setTitle(elementValue);
		else if (localName.equalsIgnoreCase("artist"))
			data.setArtist(elementValue);
		else if (localName.equalsIgnoreCase("country"))
			data.setCountry(elementValue);
		else if (localName.equalsIgnoreCase("company"))
			data.setCompany(elementValue);
		else if (localName.equalsIgnoreCase("price"))
			data.setPrice(elementValue);
		else if (localName.equalsIgnoreCase("year"))
			data.setYear(elementValue);
	}
	/**
	 * This is called to get the tags value
	 **/
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if (elementOn) {
			elementValue = new String(ch, start, length);
			elementOn = false;
		}
	}
}

In the startElement I have included a comment to show how to retrieve the attribute of an opened tag.


Step 4: Getters, Setters, and Logcat

This is a very simple class which contains arraylists, getters and setters. Here the array lists are set from the content handler class by calling their respective setter methods.

In this example, it is simple because we are basically retrieving string types. However, in other XML files you may need to retrieve other types, such as date or URL, and you will need to make adjustments as needed. Take date for example: you might have to use a date formatter to format the date correctly before you set it.

In each of the setter methods I have added logs like the one below:

Log.i('This is the value:', example);

This is very useful as you can use the Logcat that is located in the DDMS perspective to track all the data that you are retrieving for the XML. A great advantage of doing this is that if your code fails, you will know exactly at which tag the parser is failing and can make the necessary adjustments.

Below is a snippet of code from the getters and setters class showing just one of the getter and setter methods:

public class XMLGettersSetters {
private ArrayList<String> company = new ArrayList<String>();
	public ArrayList<String> getCompany() {
		return company;
	}
	public void setCompany(String company) {
		this.company.add(company);
		Log.i("This is the company:", company);
	}

Below is an image of Logcat showing all the retrieved data.

Description

Step 5: Displaying the Retrieved Data

In the activity, we will need to create an instance of the SAX parser. We also need to create the handler for each of the XML tags. We also have the URL of the XML that we need to pass into the Handler. Here is the code used to implement this:

try {
    /**
    * Create a new instance of the SAX parser
    **/
    SAXParserFactory saxPF = SAXParserFactory.newInstance();
    SAXParser saxP = saxPF.newSAXParser();
    XMLReader xmlR = saxP.getXMLReader();
    URL url = new URL("http://www.xmlfiles.com/examples/cd_catalog.xml"); // URL of the XML
    /**
    * Create the Handler to handle each of the XML tags.
    **/
    XMLHandler myXMLHandler = new XMLHandler();
    xmlR.setContentHandler(myXMLHandler);
    xmlR.parse(new InputSource(url.openStream()));
} catch (Exception e) {
    System.out.println(e);
}

The final step is to display the data to an Activity. For each data category we need to create a different TextView array. For example:

TextView example[];

By doing this, we will be able to add all the retrieved data to these TextViews. We need to make the length of the TextView the size of the TextView, the following line of code will set the TextView length to the size of the TextView array:

example = new TextView[data.getExample().size()];

We need to get the layout of the Activity in order to set all the TextViews that are created for it programmatically. Using a view we can do this simply. Below is the line of code we require:

View layout = findViewById(R.id.layout);

Now that we have the length of the TextView, we can simply run a for loop to add the data to these TextViews. The for loop will end when the end of the TextView array is reached.

Here is the code used to implement the for loop to set the data to TextViews and then set the TextViews to the layout:

for (int i = 0; i < data.getExample().size(); i++) {
			example[i] = new TextView(this);
			example[i].setText("Example= "+data.getExample ().get(i));
			example2[i] = new TextView(this);
			example2[i].setText("Example2 ="+data.get Example2().get(i));
			((ViewGroup) layout).addView(example[i]);
			((ViewGroup) layout).addView(example2[i]);
		}

The last line of code would be used to set the layout:

setContentView(layout);

Conclusion

Now that everything is set up properly, you can run your app. The results should look like the image below. If you do get an error, the most likely reason would be that you are not handling the XML correctly. The best way to approach debugging that is by using the Logcat.

Description

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Gurvinder Singh Sandhu

    nice tutorial.. keep the work up.. :)

  • Sashen Govender
    Author

    Hi Hanush,

    My objective in this article was only to show how XML can be passed using the SAX parser. However I could include this if there is a next iteration to this tutorial.

  • harilalkm

    hi it’s a nice tutorial . I have tried it and able print the details in log. But have no idea about showing it in activity.

    Is it on Activity class or in Handler class?

    • Sashen Govender
      Author

      Hi,

      Displaying the data is in the Activity. All the handler class does is read the XML file and extract the data.

      • harilalkm

        yeah i got it :) and worked for me also…

  • http://www.elbepower.com kuemmeler

    nice tutorial but how do i reach the data in my Activities?
    And from 3.0+ you need to get that url.openStream() into something like a
    thread:

    http://developer.android.com/resources/articles/painless-threading.html

    • http://www.elbepower.com kuemmeler

      finally it worked when i decreased the targetsdk down to 9, so i had not do it in a seperate thread.

      But maybe you can show us in an iteration of this tutorial how to do it in Android 3.0+.

      Thx.

  • adellphos

    Very nice tutorial. I have one question: I have seen that that in the past year there is more talking about Simple Framework as a very good XML parser for Android. What do you all say about Simple Framework?

  • reyjohn

    Hi, I tried this one, everything till the log cat view is running perfectly, but when i returning the listArray and setting it in a listview its just showing the last value of the data, not the all , M i missing something?

  • Jay

    Nearly got this working the way I want, must the late night beer, but would appreciate it if you could drop a copy to my inbox to. Hopefully you’ll get my email address from the post.

    Kind regards.

  • Daron

    ok i just need to know what data is initially set to in the Activity.

    btw, what is getExample();

    sorry but my brain is not making the connection

  • Daron

    By data I mean as in your example for using the xml data in the Activity.

    example = new TextView[data.getExample().size()];

    I just need the ‘data’ variable which I believe should be the array of xml data that was collected in XMLHandler or XMLGettersSetters. I dont need textviews. just the list of data.

    my bottom line…what is ‘data’ in the Activity part of the example.

  • Saad

    Thank you for the code.

    The code does not handle node values with new line characters. It only returns a tag’s value till the first new line character encountered.

    I had to fix this by:-

    public void characters(char[] ch, int start, int length)
    throws SAXException {

    String strChars = new String(ch, start, length);

    if (elementOn) {

    elementValue += strChars;

    }

    }

    Also set elementValue = “”; in startElement and endElement functions just in case.

  • jay

    never mind… i got it working. great tutorial btw :)

  • Bala

    thnak u. Iy s working well and very usefull for me. But i want to load the values from my local. how to do this?
    Can anyone help me.

    Advance thanks

    • Ron

      The way I load from local is.

      in step 5, replace

      URL url = new URL(“http://www.xmlfiles.com/examples/cd_catalog.xml”); // URL of the XML

      with

      InputStream localFile;

      localFile = this.getResources().openRawResource(R.raw.nameofxmlfile.xml);

      Hope that helps

  • sravanthi

    Hi,

    I just want to show a title in the list activity using this parser? how can i do that?

  • irfan

    hi
    nice tutorial its working ,but accesing xml from local server it showing null pointer exception

  • Zeynel

    Hi
    How can Parsing an image from XML ?

    Thnx

  • http://www.tick2click.com Kamal Sharma

    Such a Wonderful post….
    Thanks a lot for this post…
    I am trying it since last 2 days…
    You made it easy….
    Thank You So much

  • Manjunath

    nice tutorial but I have tried to executing this application java.lang.ArrayIndexOutOfBoundsException will happen..

  • http://bdwm.be Jules

    Thanks for this nice tutorial. It was fairly simple, but I think you made it a little overcomplicated with the dynamically generated text fields. You could have just done txtField.append(“….\n”) imo. Apart from that. Very simple and to the point. Nice example data too.

  • chess

    Thanks for this tutorial.
    I have though a question:
    in my xml file I have a tag that doesn’t end normally
    actually it appears like this:

    So you may remark that there isn’t a tag of end.
    This prohibit to me to extract the content between the two tags.
    Does anyone have some ideas?
    :(

  • devraj

    hi, parsing a xml file into android is not a very difficult for me, but currently i am working on a project in with i have to parse the data from xml and save this into the local sqlite database. i dont have to use any webservices to use.. this is only for personal use for a client.
    i have to save parsed data in sqlite database and also provide feature to update that sqlite data base that will also generate a updated XML file in his mobile only and he want to take that XML file out from his phone to hi laptop by using datacable..
    how can we do this.. plz show me some examples for that??
    really required some help.

  • edwin

    How I can give a different order to display the TextView[]; it in the UI or XML?

  • Aniket

    Nice tutorial on sax parsing…

    Please also give tutorial on Json parsing(web service tutorial) and Pullparser tutorial.

  • http://www.spaninfoway.com Priyank Joshi

    Thanks for the great tutorial..much appreciated..

  • Shiv

    hello, i just wanted to know weather we can use this technique to parse rss feeds too? Reply plz..

  • delmoras

    If we wanto to show an image from xml how can we do it?

  • joe

    maxxa work dude,

  • Jon

    This was a life save!!! Thank you so much for posting this. I was so close yet so far.. and making it too hard of course.. lol. Anyway.. thank you so much friend! :)