Search This Blog

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

29 comments:

  1. Hello, I'm new at this.

    how would I go about changing the
    InputStream is = getAssets().open("xmldocument.xml"); to an URL?

    ReplyDelete
    Replies
    1. No need to change anything..you just need an Input Stream from URL like this

      try{
      URL url=new URL("your url here");
      InputStream is=url.openStream(); // Use this InputStream to parse
      }catch (Exception e) {
      }

      Delete
  2. nice post, tofeeq but i want to know i we are using more than one parent node in our xml file like: here you are using parent node, but i also want to add parent node but attributes are same in parent node, please let me know what are the changes required in java class....

    ReplyDelete
    Replies
    1. I am not able to understand your problem..can you post one complete node here so that i can help you

      Delete
  3. i googled a lot, and finally found something i want..
    nyc tut..

    can u pls upload a tutorial, that parse xml file with async task by making http request, and it should use sax or pull parser.
    tenx in advance..:)

    ReplyDelete
    Replies
    1. Thanks vaishali..I will post but it may take few days.If you have any urgent need contact me on my google plus profile. I will guide you

      Delete
  4. also pls explain how can i use onclickListener here on list item.
    will be highly thankful to u!!..

    ReplyDelete
    Replies
    1. HI ..if you want set click listener then use Listview.setonItemClickListner. See Article for detail ListView Simple Example

      Delete
  5. hi tofeeq,
    really nice tutorial..and easy for new ones....i have a doubt in parsing an image from xml using sax parser....i mean
    want to convert src.

    ReplyDelete
    Replies
    1. You should add this comment in you above..For image you have to parse and Image Url from your response and then use my download manager to convert this url to bitmap and set as a background of your image Image Downloader For Lazy Loading and Caching image

      Delete
  6. hi tofeeq,

    how to sort xml by specific atribute such as into alphabetical sequence so listview will show with the a letter first ?

    thanks in advance

    ReplyDelete
    Replies
    1. I think, we do not need to sort XML. In place of that when you parse data and save it inside array then you can sort these array easily , And Finally pass these array to list Adapter. It will show same sequence

      Delete
  7. hi tofeeq, i have doubt in android web service . i could not get best site to learn.. u have any tutorials for android webservice using SOAP .....

    ReplyDelete
  8. hi
    i am currently working on tfl tube routing. can u help me in parsing the xml file using asynctASK. bcos without asynctask, it wont support in 4.0 devices

    ReplyDelete
    Replies
    1. Hi, i got many request to show how to parse using Thread or asynchronous task. I will post soon on this. Keep visiting..Or you can see this article AsynChronous Task , you have to just put parsing code inside doInBackground()

      Delete
  9. hi tofeeq, i just want to create a xml file in Android.....i used XMLTextWriter but not supported in android bcos it comes under javax library. its possible to create xml using sax Tofeeq? or give some tutorials or guides?

    ReplyDelete
    Replies
    1. Creating xml is completely different. I will get back to you if i got any information on that

      Delete
  10. AOA Tofeeq, I have seen your posts, really amazing and helpful. I am new to Android and i am struggling to handle XML from TFL. Link for TFL tube is given below:
    http://cloud.tfl.gov.uk/TrackerNet/PredictionDetailed/C/BNK

    To be honest, i am searching the internet since last three days and i have found some examples about XML parsing but i am unable to apply the same concept on TFL XML. I am really struggling.....

    Can you please show me an example by using the above online TFL XML data. I really appreciate your help. Waiting for your reply....

    MUHAMMAD

    ReplyDelete
    Replies
    1. In ParsingClass, you need to get attribute rather then tag to read values of N, Cur Time in S Code="BNK" Mess="" N="Bank." CurTime="4:10:57". For ex. in startElement method attr is already there so you just need to call

      if (localName.equals("S")) {
      atts.getValue("Code") // like for all
      }

      Delete
  11. Hi Tofeeq,

    First of all a big Thanx to you for this live working example. I am a very beginner to Java/Android and was trying to learn SAX parsing. This example showed me the way. Although i have one doubt here, i copied your exact code and tried to run the app in mobile. I am able to see the data only when i press a row,else not. Could you please explain why it is so.

    Thanks
    Manish

    ReplyDelete
    Replies
    1. As far as i know if you are getting data when press row. Then your ListView background color and ListRow's child(The layout we used to showing in ListRow) text color are same.Try to change colors

      Delete
    2. Thanks, i changed the colour of the text and it worked. I am trying to understand the whole logic of parsing step by step. If stuck somewhere , i know where to get help :-)

      Delete
    3. Your welcome..Keep visiting this blog. And share with your friends :)

      Delete
    4. Could you please guide me , how to show a progress dialog while my Listview is getting populated through online data. I am using above example only for my code.

      Delete
    5. Use Asynchronous Task to showing progress dialog until you load your data from on line URL

      Delete
    6. Hi manish,
      This is QA forum, So please do not paste your complete code here.I consider it spam and delete your comment.Hope you understand

      Delete
  12. hiii tofeeq good to see your code Man tell me one thing why xml not getting in terms of different url.just check the code at androidhive parsing xml by xmlparser.issue is that when url changed app carshed any reason do share to me Thanks In Advance...

    ReplyDelete
    Replies
    1. I do not why application crash. But if you change URL then you have change the Tag you are trying to read. These tag should be valid

      Delete

Feedback always help in improvement. If you have any query suggestion feel free to comment and Keep visiting my blog to encourage me to blogging

Android News and source code