Android: Parsing XML with children and attributes using SAX

22 November 2012 By Nithya Vasudevan 7,562 views One Comment
7 Flares Twitter 0 Facebook 0 Google+ 7 7 Flares ×

Project Description

  • In one of the previous Android example we saw how to parse a simple XML using SAX parser.
  • This example shows how to parse a XML containing element attributes, multi-level child nodes using Android SAX parser.
  • In this example, we are going to store the XML file in project’s assets folder and open the file as InputStream using AssetManager.
  • On button click event, we parse the XML and display the result in ListView. When the list item is clicked a Toast message is displayed with detailed description of XML element.

To parse an XML in Android, you can use DOM and SAX parser API provided by Java platform. In addition to these two parsers, Android provides XmlPullParser which is similar to StAX parser and also the recommended parser to be used in Android.

Environment Used

  • JDK 6 (Java SE 6)
  • Eclipse Indigo IDE for Java EE Developers (3.7.1)
  • Android SDK 4.0.3 / 4.1 Jelly Bean
  • Android Development Tools (ADT) Plugin for Eclipse (ADT version 20.0.0)
  • Refer this link to setup the Android development environment

Prerequisites

Create Android Project

  • Create a new Android Project and name it as “SAXParserAttrChildNodes“.
  • Enter the package name as “com.theopentutorials.android.activities“.
  • Enter the Activity name as “SAXParserActivity“.
  • Click Finish.

Create XML file

In the project’s assets folder, create a new XML file and name it as “employees.xml” and copy the following.

<?xml version="1.0" encoding="UTF-8"?>
<employees>
	<employee id = "6743">
		<name>Ram</name>
		<department>Development</department>
		<type>Permanent</type>		
		<email>[email protected]</email>
		<address>
	        <line1>163 Main Street</line1>
	        <city>Chennai</city>
	        <state>TN</state>
	        <zipcode>600001</zipcode>
   		</address>
	</employee>
	<employee id = "6752">
	    <name>Siva</name>
		<department>DB</department>
		<type>Contract</type>		
		<email>[email protected]</email>
		<address>
	        <line1>1201 Main Rd</line1>
	        <city>Peoria</city>
	        <state>Illinois</state>
	        <zipcode>61606</zipcode>
   		</address>
	</employee>	
	<employee id = "6763">
	    <name>Timmy</name>
		<department>Testing</department>
		<type>Permanent</type>		
		<email>[email protected]</email>
		<address>
	        <line1>2163 1st Avenue</line1>
	        <city>Chicago</city>
	        <state>Illinois</state>
	        <zipcode>60631</zipcode>
   		</address>
	</employee>
</employees>

strings.xml

Open res/values/string.xml and replace it with following content.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, SAXParserActivity!</string>
    <string name="app_name">SAXParserAttrChildNodes</string>
    <string name="button">Parse XML using SAX</string>
</resources>

XML layout files

main layout file (main.xml)

This file defines a layout for displaying the result of SAX parser in ListView.
Open main.xml file in res/layout and copy the following content.

<?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" >

 <Button
        android:id="@+id/button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/button" />
    
   <ListView
        android:id="@+id/employeeList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
       />
</LinearLayout>

ListView row layout file (list_item.xml)

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/title"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:textColor="#CC0033"
    android:textSize="16sp" />

Create Bean class

Address.java

Create a new Java class “Address.java” in package “com.theopentutorials.android.beans” and copy the following code.

package com.theopentutorials.android.beans;

public class Address {
	private String line;
	private String city;
	private String state;
	private long zipcode;

	public String getLine() {
		return line;
	}

	public void setLine(String line) {
		this.line = line;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public long getZipcode() {
		return zipcode;
	}

	public void setZipcode(long zipcode) {
		this.zipcode = zipcode;
	}	
}

Employee.java

Create a new Java class “Employee.java” in package “com.theopentutorials.android.beans” and copy the following code.

package com.theopentutorials.android.beans;

public class Employee {

	private String name;
	private int id;
	private String department;
	private String type;
	private String email;
	private Address address;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getDepartment() {
		return department;
	}

	public void setDepartment(String department) {
		this.department = department;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return id + ": " + name + "\n" + department + "-" + type;
	}

	public String getDetails() {
		String result = id + ": " + name + "\n" + department + "-" + type
				+ "\n" + email + "\n" + "Address:\n" + address.getLine() + "\n"
				+ address.getCity() + ", " + address.getState() + " "
				+ address.getZipcode();
		return result;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}
}

Create SAXXMLHandler class

Create a new Java class “SAXXMLHandler.java” in package “com.theopentutorials.android.xml” and copy the following code.

package com.theopentutorials.android.xml;

import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.theopentutorials.android.beans.Address;
import com.theopentutorials.android.beans.Employee;

public class SAXXMLHandler extends DefaultHandler {

	private List<Employee> employees;
	private String tempVal;
	// to maintain context
	private Employee employee;
	private Address address;

	public SAXXMLHandler() {
		employees = new ArrayList<Employee>();
	}

	public List<Employee> getEmployees() {
		return employees;
	}

	// Event Handlers
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		// reset
		tempVal = "";
		if (qName.equalsIgnoreCase("employee")) {
			// create a new instance of employee
			employee = new Employee();
			employee.setId(Integer.parseInt(attributes.getValue("id")));
		} else if (qName.equalsIgnoreCase("address")) {
			// create a new instance of address
			address = new Address();
		}
	}

	public void characters(char[] ch, int start, int length)
			throws SAXException {
		tempVal = new String(ch, start, length);
	}

	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if (qName.equalsIgnoreCase("employee")) {
			// add it to the list
			employees.add(employee);
		} else if (qName.equalsIgnoreCase("name")) {
			employee.setName(tempVal);
		} else if (qName.equalsIgnoreCase("department")) {
			employee.setDepartment(tempVal);
		} else if (qName.equalsIgnoreCase("type")) {
			employee.setType(tempVal);
		} else if (qName.equalsIgnoreCase("email")) {
			employee.setEmail(tempVal);
		} else if (qName.equalsIgnoreCase("line1")) {
			address.setLine(tempVal);
		} else if (qName.equalsIgnoreCase("city")) {
			address.setCity(tempVal);
		} else if (qName.equalsIgnoreCase("state")) {
			address.setState(tempVal);
		} else if (qName.equalsIgnoreCase("zipcode")) {
			address.setZipcode(Long.parseLong(tempVal));
		} else if (qName.equalsIgnoreCase("address")) {
			employee.setAddress(address);
		}
	}
}

SAX (Simple API for XML) is an event-based sequential access parser API with number of callback methods that will be called when events occur during parsing. This class parses a XML file containing employee details and stores in a list as an employee object.

Create SAXXMLParser class

Create a new Java class “SAXXMLParser.java” in package “com.theopentutorials.android.xml” and copy the following code.

package com.theopentutorials.android.xml;

import java.io.InputStream;
import java.util.List;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import com.theopentutorials.android.beans.Employee;
import android.util.Log;

public class SAXXMLParser {

	public static List<Employee> parse(InputStream is) {
		List<Employee> employees = null;
		try {
			// create a XMLReader from SAXParser
			XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser()
					.getXMLReader();
			// create a SAXXMLHandler
			SAXXMLHandler saxHandler = new SAXXMLHandler();
			// store handler in XMLReader
			xmlReader.setContentHandler(saxHandler);
			// the process starts
			xmlReader.parse(new InputSource(is));
			// get the `Employee list`
			employees = saxHandler.getEmployees();

		} catch (Exception ex) {
			Log.d("XML", "SAXXMLParser: parse() failed");
		}

		// return Employee list
		return employees;
	}
}

Create SAXParserActivity class

package com.theopentutorials.android.activities;

import java.io.IOException;
import java.util.List;
import com.theopentutorials.android.activities.R;
import com.theopentutorials.android.beans.Employee;
import com.theopentutorials.android.xml.SAXXMLParser;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class SAXParserActivity extends Activity implements
		OnClickListener, OnItemClickListener {

	Button button;
	ListView listView;
	List<Employee> employees = null;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		findViewsById();
		button.setOnClickListener(this);

	}

	private void findViewsById() {
		button = (Button) findViewById(R.id.button);
		listView = (ListView) findViewById(R.id.employeeList);
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		Employee employee = employees.get(position);
		Toast.makeText(parent.getContext(), employee.getDetails(),
				Toast.LENGTH_LONG).show();
	}

	@Override
	public void onClick(View view) {
		try {
			employees = SAXXMLParser.parse(getAssets().open("employees.xml"));
			ArrayAdapter<Employee> adapter = new ArrayAdapter<Employee>(this,
					R.layout.list_item, employees);
			listView.setAdapter(adapter);
			listView.setOnItemClickListener(this);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.theopentutorials.android.xml.sax"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name="com.theopentutorials.android.activities.SAXParserActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Output

Run your application

Project Folder Structure

The complete folder structure of this example is shown below.

Tags: , , , , , , , , , , , , , , , ,

  • Vajeng Patidar

    Hi,Its very practical and helpful tutorial.
    how could will display detail list on second activity if we click item on first activity.
    Thanks a lots.