天天看點

Android:SAX解析XML檔案

     SAX解析XML檔案主要通過一個類DefaultHandler來實作,在這個類中重寫四個方法;startDocument()、startElement(String uri, String localName, String qName,Attributes attributes)、characters(char[] ch, int start, int length)、endElement(String uri, String localName, String qName)。由上述四個方法可以看出,其解析過程是一個個元素解析下去的。

    首先自定義一個XML檔案:Student.xml,注意是建立file而不是xml。

<?xml version="1.0" encoding="utf-8"?>
<students>
	<student id="1">
		<name>張三</name>
		<sex>男</sex>
		<age>18</age>
	</student>
	<student id="2">
		<name>李四</name>
		<sex>女</sex>
		<age>19</age>
	</student>
	<student id="3">
		<name>王五</name>
		<sex>男</sex>
		<age>20</age>
	</student>
</students>
           

    然後建立一個student類

package com.example.xml_sax_demo_1;
public class Student {
	private int id;
	private String name;
	private String sex;
	private int age;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}

}
           

    接下來是最重要一步,建立一個類繼承DefaultHandler

package com.example.xml_sax_demo_1;
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 android.R.integer;

public class SAXForHandler extends DefaultHandler {
	private List<Student> list;  //将解析的資料放在一個List裡面
	private Student student;
	private String tagName;   //存放元素名稱
	public List<Student> getList() {
		return list;
	}
	@Override
	public void startDocument() throws SAXException {
		list = new ArrayList<Student>();   //開始解析時執行個體化list
	}
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		if (qName.equals("student")) {                  //每個元素都是一個element    
			student = new Student();                //例如上面xml檔案中的student、name、sex、age
			// 擷取student節點上的id屬性值          
			student.setId(Integer.parseInt(attributes.getValue(0)));    //屬性和文本有所不同
		}
		this.tagName = qName;                           //将元素名稱賦給标志,為下一步做準備
	}
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if (qName.equals("student")) {                 //如果是student說明我們解析完了一項資料
			this.list.add(this.student);
		}
		this.tagName = null;                           //将标志置為null
	}
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if (this.tagName != null) {       //如果tagName不為null,之前看過一篇文章,元素前的空白處也是會被解析的。
			String date = new String(ch, start, length);   //開始存放資料
			if (this.tagName.equals("name")) {
				this.student.setName(date);
			} else if (this.tagName.equals("sex")) {
				this.student.setSex(date);
			} else if (this.tagName.equals("age")) {
				this.student.setAge(Integer.parseInt(date));
			}
		}
	}
}
           

以解析第一項資料為例:

<students>
	<student id="1">
		<name>張三</name>
		<sex>男</sex>
		<age>18</age>
	</student>
           

整個流程是:startDocument:執行個體化list  →  startElement:元素名為student,将其屬性賦給student的字段id,tagName = student  → endElement: tagName = null  →  startElement:tagName = name  →   characters:元素名為name,将資料賦給student相應字段  →  endElement:tagName = null  →  .......  → endElement:tagName為student,将一項資料存放在list裡面。可以這樣了解:遇到<type>就是startElement,遇到</type>就是endElement。

最後在activity裡面通過一個Button來解析資料,其中用到幾個類。

package com.example.xml_sax_demo_1;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

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

import org.xml.sax.SAXException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Xml;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends ActionBarActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button button = (Button) findViewById(R.id.button);
		button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				try {
					readXML();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
	}

	private void readXML() throws Exception {
		SAXParserFactory spf = SAXParserFactory.newInstance();
		SAXParser parser = spf.newSAXParser();
		SAXForHandler parseXml = new SAXForHandler(); // 執行個體化解析類
		InputStream stream = this.getClass().getClassLoader()
				.getResourceAsStream("Student.xml"); // 獲得輸入流
		parser.parse(stream, parseXml); // 兩個參數,一個是輸入流,一個是解析類對象。
		List<Student> list = parseXml.getList();
		for (Student student : list) {
			System.out.println(student.getId() + " " + student.getName() + " "
					+ student.getSex() + " " + student.getAge());
		}
	}
}
           

結果:

Android:SAX解析XML檔案

小結:注意xml檔案的解析過程,完全自己寫的demo一直會出現inputstream can not be null的錯誤,估計是XML寫得有問題~~