XML stands for Extensible Markup Language. XML is a very popular format and commonly used for sharing data on the internet. This chapter explains how to parse the XML file and extract necessary information from it.
Android provides three types of XML parsers which are
DOM
, SAX
and XMLPullParser
. Among all of them, I recommend XMLPullParser
because it is efficient and easy to use. In this post, I present a simple example to get XML data from an URL
by AsyncTask
and parse it using XMLPullParser
.1. Launch Eclipse and start a new Android Project (I use min-sdk is 14).
2. Create layout for activity (activity_weather.xml):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical"
tools:context=".WeatherActivity" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:gravity="center"
android:text="@string/notice"
android:textSize="18sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/country" />
<TextView
android:id="@+id/country"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_green_light" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal" >
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/location" />
<TextView
android:id="@+id/location"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_blue_dark" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/temperature"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/temperature"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_orange_dark" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/humidity"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/humidity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_purple" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/textView5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/pressure" />
<TextView
android:id="@+id/pressure"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_red_dark" />
</LinearLayout>
</LinearLayout>
3. Create an AsyncTask
to get XML data. This class deals with following operations:- Getting XML content by making HTTP request (in
doInBackground()
method). - Parsing XML content and getting element of xml (
parseXML()
method).
Getting XML content by making HTTP request
@Override
protected String[] doInBackground(String[]... params) {
try {
URL url = new URL(this.url);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(10000 /* milliseconds */);
connection.setConnectTimeout(15000 /* milliseconds */);
connection.setRequestMethod("GET");
connection.setDoInput(true);
connection.connect();
InputStream stream = connection.getInputStream();
xmlFactoryObject = XmlPullParserFactory.newInstance();
XmlPullParser myParser = xmlFactoryObject.newPullParser();
myParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
myParser.setInput(stream, null);
String[] result = parseXML(myParser);
stream.close();
return result;
} catch (Exception e) {
e.printStackTrace();
Log.e("AsyncTask", "exception");
return null;
}
}
Parsing XML content and getting DOM
element of xml
public String[] parseXML(XmlPullParser myParser) {
int event;
String text = null;
String[] result = new String[5];
try {
event = myParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String name = myParser.getName();
switch (event) {
case XmlPullParser.START_TAG:
break;
case XmlPullParser.TEXT:
text = myParser.getText();
break;
case XmlPullParser.END_TAG:
//get country name
if (name.equals("country")) {
result[4] = text;
} else if (name.equals("humidity")) { //get humidity
result[0] = myParser.getAttributeValue(null, "value");
} else if (name.equals("pressure")) { //get pressure
result[1] = myParser.getAttributeValue(null, "value");
} else if (name.equals("temperature")) { //get temperature
result[2] = myParser.getAttributeValue(null, "value");
} else if (name.equals("coord")) { //get location
result[3] = "(" + myParser.getAttributeValue(null, "lat") + " , "
+ myParser.getAttributeValue(null, "lon") + ")";
}
break;
}
event = myParser.next();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
GetWeatherDataTask.java
:
package com.blogspot.hongthaiit.xmlandasynctask;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Log;
public class GetWeatherDataTask extends AsyncTask<String[], Void, String[]> {
private WeatherActivity activity;
private String url;
private XmlPullParserFactory xmlFactoryObject;
private ProgressDialog pDialog;
public GetWeatherDataTask(WeatherActivity activity, String url) {
this.activity = activity;
this.url = url;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(activity);
pDialog.setTitle("Get Weather Information from XML");
pDialog.setMessage("Loading...");
pDialog.show();
}
@Override
protected String[] doInBackground(String[]... params) {
try {
URL url = new URL(this.url);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(10000 /* milliseconds */);
connection.setConnectTimeout(15000 /* milliseconds */);
connection.setRequestMethod("GET");
connection.setDoInput(true);
connection.connect();
InputStream stream = connection.getInputStream();
xmlFactoryObject = XmlPullParserFactory.newInstance();
XmlPullParser myParser = xmlFactoryObject.newPullParser();
myParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
myParser.setInput(stream, null);
String[] result = parseXML(myParser);
stream.close();
return result;
} catch (Exception e) {
e.printStackTrace();
Log.e("AsyncTask", "exception");
return null;
}
}
public String[] parseXML(XmlPullParser myParser) {
int event;
String text = null;
String[] result = new String[5];
try {
event = myParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String name = myParser.getName();
switch (event) {
case XmlPullParser.START_TAG:
break;
case XmlPullParser.TEXT:
text = myParser.getText();
break;
case XmlPullParser.END_TAG:
//get country name
if (name.equals("country")) {
result[4] = text;
} else if (name.equals("humidity")) { //get humidity
result[0] = myParser.getAttributeValue(null, "value");
} else if (name.equals("pressure")) { //get pressure
result[1] = myParser.getAttributeValue(null, "value");
} else if (name.equals("temperature")) { //get temperature
result[2] = myParser.getAttributeValue(null, "value");
} else if (name.equals("coord")) { //get location
result[3] = "(" + myParser.getAttributeValue(null, "lat") + " , "
+ myParser.getAttributeValue(null, "lon") + ")";
}
break;
}
event = myParser.next();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
protected void onPostExecute(String[] result) {
//call back data to main thread
pDialog.dismiss();
activity.callBackData(result);
}
}
4. As you can see, at onPostExcute()
, data were return to main thread. So we use them to set views.Full
WeatherActivity.java
code simple like this:
package com.blogspot.hongthaiit.xmlandasynctask;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class WeatherActivity extends Activity {
private final static String url = "http://api.openweathermap.org/data/2.5/weather?q=hanoi&mode=xml";
private TextView location, country, temperature, humidity, pressure;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weather);
location = (TextView) findViewById(R.id.location);
country = (TextView) findViewById(R.id.country);
temperature = (TextView) findViewById(R.id.temperature);
humidity = (TextView) findViewById(R.id.humidity);
pressure = (TextView) findViewById(R.id.pressure);
new GetWeatherDataTask(this, url).execute();
}
public void callBackData(String[] result) {
temperature.setText((Float.parseFloat(result[2]) - 273) + " degree Celcius" );
humidity.setText(result[0] + " %");
pressure.setText(result[1] + " hPa");
country.setText(result[4]);
location.setText(result[3]);
}
}
5. Open AndroidManifest.xml
and add permission to access Internet:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.blogspot.hongthaiit.xmlandasynctask"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".WeatherActivity"
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>
6. Some application screens (click for full size):