Thursday, 16 February 2012

XML parsing tutorial using Sax Parser in android

Parsing is an important phase in android application development. Storing data on android device is not feasible  in large amount of data. So we store data on server and return data in xml format and then we parse data and show data on android device.

You can create a InputStream either from online URL or from local file.I stored a xml file into assets and make an InputStream and  parse it.

XML to parse

<main>
 <student>
  <name> Tofeeq Ahmad</name>
  <address> 142, Karol Bag, Delhi </address>
  <qua> MCA</qua>
 </student>
 <student>
  <name> Sameer Ahmad</name>
  <address> 142, Karol Bag,New  Delhi </address>
  <qua> BCA </qua>
 </student>
 <student>
  <name> Adams Cinclear</name>
  <address>123, Street Road Las Vegas </address>
  <qua> B Tech</qua>
 </student>
 <student>
  <name> Mike Hussy</name>
  <address> Sydney Australia </address>
  <qua> B.Com </qua>
 </student>
 <student>
  <name> Sameer Ahmad</name>
  <address> 142, Karol Bag,New  Delhi </address>
  <qua> BCA </qua>
 </student>
 <student>
  <name> Kushal Pal Singh</name>
  <address> 142, Karol Bag,New  Delhi </address>
  <qua> M Tech </qua>
 </student>
</main>

Now we will create a an application with ListView that will parse data and display it on ListView'row.

Step 1) Create two Layout  One main screen that contain one ListView and other to display data inside a row

 Layout for Main Screen

<?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" >
    <ListView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/listview"
        android:cacheColorHint="@android:color/transparent"
        android:dividerHeight="2dp"
        />
</LinearLayout>

Layout for listview row
<?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="wrap_content"
    android:orientation="vertical"
    android:paddingLeft="10dp" >

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sameer Ahmad"
        android:textColor="#fff"
        android:textSize="18dp" />

    <TextView
        android:id="@+id/address"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sameer Ahmad"
        android:textColor="#fff"
        android:textSize="18dp" />

    <TextView
        android:id="@+id/quali"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sameer Ahmad"
        android:textColor="#fff"
        android:textSize="18dp" />

</LinearLayout>

Step 2) Now we will parse data using default handler that is part of Sax Parser. In this class we have three method startElement , endElement , character. These called when tag start , tag end and read its values. We will save these values inside corresponding values


package com.ahmad;

import java.util.ArrayList;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class ParsingClass extends DefaultHandler {

 ArrayList<String> name = new ArrayList<String>();
 ArrayList<String> address = new ArrayList<String>();
 ArrayList<String> qua = new ArrayList<String>();

 @Override
 public void startElement(String uri, String localName, String qName,
   Attributes attributes) throws SAXException {
  super.startElement(uri, localName, qName, attributes);
  if (localName.equalsIgnoreCase("name")) {
   tempStore = "";
  } else if (localName.equalsIgnoreCase("address")) {
   tempStore = "";
  } else if (localName.equalsIgnoreCase("qua")) {
   tempStore = "";
  }else{
   tempStore = "";
  }
 }

 @Override
 public void endElement(String uri, String localName, String qName)
   throws SAXException {
  super.endElement(uri, localName, qName);
  if (localName.equalsIgnoreCase("name")) {
   name.add(tempStore);
  } else if (localName.equalsIgnoreCase("address")) {
   address.add(tempStore);
  } else if (localName.equalsIgnoreCase("qua")) {
   qua.add(tempStore);
  }
  tempStore = "";
 }

 private String tempStore = "";

 @Override
 public void characters(char[] ch, int start, int length)
   throws SAXException {
  super.characters(ch, start, length);
  tempStore += new String(ch, start, length);
 }
}

Step 3) Now we need one Activity to create core component of parsing and Setting InputStream from assets. and Finally when data will parse we will add or bind all data to listview

Activity class with core parsing code

package com.ahmad;

import java.io.InputStream;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class XmlParsingActivity extends Activity {
 /** Called when the activity is first created. */
 private ListView listView;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  listView = (ListView) findViewById(R.id.listview);
  bindDataToListing();
 }

 private void bindDataToListing() {
  try {
   SAXParserFactory saxparser = SAXParserFactory.newInstance();
   SAXParser parser = saxparser.newSAXParser();
   XMLReader xmlReader = parser.getXMLReader();
   ParsingClass pc = new ParsingClass();
   xmlReader.setContentHandler(pc);
   InputStream is = getAssets().open("xmldocument.xml");
   xmlReader.parse(new InputSource(is));
   BindingData bindingData = new BindingData(this, pc.name,
     pc.address, pc.qua);
   listView.setAdapter(bindingData);
  } catch (Exception e) {
   e.getMessage();
  }
 }
}

Adapter Class For Binding data to ListView..if you are new to this see article ListView with adapter 

package com.ahmad;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class BindingData extends BaseAdapter {
 ArrayList<String> name;
 ArrayList<String> address;
 ArrayList<String> qua;
 LayoutInflater inflater;

 public BindingData() {

 }

 public BindingData(Activity act, ArrayList<String> name,
   ArrayList<String> add, ArrayList<String> qua) {
  this.name = name;
  this.address = add;
  this.qua = qua;
  inflater = (LayoutInflater) act
    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 }

 @Override
 public int getCount() {
  return name.size();
 }

 @Override
 public Object getItem(int position) {
  return null;
 }

 @Override
 public long getItemId(int position) {
  return 0;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  Holder holder;
  if (convertView == null) {
   holder = new Holder();
   convertView = inflater.inflate(R.layout.listrow, null);
   holder.txtName = (TextView) convertView.findViewById(R.id.name);
   holder.txtAddress = (TextView) convertView
     .findViewById(R.id.address);
   holder.txtQua = (TextView) convertView.findViewById(R.id.quali);
   convertView.setTag(holder);
  } else {
   holder = (Holder) convertView.getTag();
  }
  holder.txtName.setText(Html.fromHtml("" + name.get(position)));
  holder.txtAddress.setText(Html.fromHtml("<b>Address : </b>"
    + address.get(position)));
  holder.txtQua.setText(Html.fromHtml("<b>Qualification : </b>"
    + qua.get(position)));

  return convertView;
 }

 private class Holder {
  TextView txtName, txtAddress, txtQua;
 }
}

Finally you hard work will bring output like this


Download Source Code