天天看點

Android網絡下解析XML

XML(Extensible Markup Language)可拓展标記語言,它與HTML一樣,都是SGML(标準通用标記語言),它可以用來标記資料、定義資料類型,是一種允許使用者對自己的标記語言進行定義的源語言。 它非常适合網際網路傳輸,提供統一的方法來描述和交換獨立于應用程式或供應商的結構化資料。在Android下有三種方式解析XML,分别為SAX、DOM、PULL;它們有各自的特點,在網絡程式設計中會經常使用,根據實際情況選擇哪一種解析方式。

1、記憶體占用

由于Android手機性能相對于PC還是相當有限的,程式對記憶體的占用直接影響到解析XML的速度,在記憶體占用的情況上,SAX、Pull要比DOM占用的少些

2、程式設計方式

SAX采用事件驅動,每解析一類XML都要編寫一個适合該類的XML處理類;DOM是W3C的規範,很多語言都可以使用,使用起來較友善,Pull是Android自帶的解析XML,使用較少的解析器。

SAX與PULL比較類似,适用處理大型文檔,隻需要文檔中部分的内容;而DOM适用于小型文檔,随機通路,需要對文檔進行修改。

下面看下在代碼中是如何使用的

程式目錄結構

Android網絡下解析XML

需要解析的XML檔案file.xml

<?xml version="1.0" encoding="utf-8"?>
<persons>

    <person id="10" >
        <name>張三</name>
        <age>25</age>
        <sex>男</sex>
    </person>
    
    <person id="11" >
        <name>李四</name>
        <age>23</age>
        <sex>女</sex>
    </person>

    <person id="12" >
        <name>王五</name>
        <age>24</age>
        <sex>女</sex>
    </person>
    
    <person id="13" >
        <name>趙六</name>
        <age>21</age>
        <sex>男</sex>
    </person>
    
</persons>
           

解析對象

package com.dzt.xml_parser.domain;

public class Person {

	private int id;
	private String name;
	private short age;
	private String sex;

	public Person() {

	}

	public Person(int id, String name, short age, String sex) {
		this.id = id;
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	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 short getAge() {
		return age;
	}

	public void setAge(short age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", age=" + age
				+ ", sex=" + sex + "]";
	}
}
           

一、使用SAX解析XML

package com.dzt.xml_parser;

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.dzt.xml_parser.constant.GlobalConstants;
import com.dzt.xml_parser.domain.Person;

/**
 * SAX 解析類,根據實際情況修改
 * 
 * @author Administrator
 * @date 2014.05.29
 */
public class SAXHandler extends DefaultHandler {

	private List<Person> persons;
	private String preTag; // 記錄前一個标簽
	private Person person;

	public List<Person> getPerson() {
		return persons;
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		// TODO Auto-generated method stub
		String data = new String(ch, start, length).trim(); // 去掉空格
		if (!"".equals(data)) {
			GlobalConstants.PrintLog_D("[SAXHandler]->characters data = "
					+ data);
		}
		if ("name".equals(preTag)) {
			person.setName(data);
		} else if ("age".equals(preTag)) {
			person.setAge(new Short(data));
		} else if ("sex".equals(preTag)) {
			person.setSex(data);
		}
	}

	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		GlobalConstants.PrintLog_D("[SAXHandler]->endDocument");
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		// TODO Auto-generated method stub
		GlobalConstants.PrintLog_D("[SAXHandler]->endElement");
		// 到一個節點的結束
		if ("person".equals(localName)) {
			persons.add(person);
			person = null;
		}
		preTag = null;
	}

	/**
	 * 解析一個xml文檔的開始,在這裡做初始化工作
	 */
	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		GlobalConstants.PrintLog_D("[SAXHandler]->startDocument");
		persons = new ArrayList<Person>();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		if ("person".equals(localName)) {
			person = new Person();
			person.setId(Integer.valueOf(attributes.getValue(0)));
		}
		preTag = localName;
		GlobalConstants
				.PrintLog_D("[SAXHandler]->startElement--end localName = "
						+ localName + " qName = " + qName);
	}

}
           

它是以事件觸發,一個節點一個節點去解析

對代碼進行單元測試,如果不清楚如何添加單元測試可以參考:http://blog.csdn.net/deng0zhaotai/article/details/11482847

public void testSAXGetPersons() throws Exception {
		InputStream is = getContext().getResources().getAssets()
				.open("file.xml");
		SAXHandler handler = new SAXHandler();
		SAXParserFactory spf = SAXParserFactory.newInstance();
		SAXParser saxParser = spf.newSAXParser();
		saxParser.parse(is, handler);
		List<Person> list = handler.getPerson();
		is.close();
		for (Person person : list) {
			GlobalConstants.PrintLog_D("[SAXTest]->testSAXGetPersons"
					+ person.toString());
		}
	}
           

測試結果

Android網絡下解析XML

二、使用PULL解析XML

package com.dzt.xml_parser;

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

import org.xmlpull.v1.XmlPullParser;

import android.util.Xml;

import com.dzt.xml_parser.domain.Person;

public class PULLHandler {

	public static List<Person> getPersons(InputStream is) throws Exception {
		List<Person> list = null;
		Person person = null;
		XmlPullParser parser = Xml.newPullParser();
		parser.setInput(is, "UTF-8"); // 設定字元編碼
		int event = parser.getEventType(); // 觸發的第一個事件
		while (event != XmlPullParser.END_DOCUMENT) {
			switch (event) {
			case XmlPullParser.START_DOCUMENT: // 開始解析
				list = new ArrayList<Person>();
				break;
			case XmlPullParser.START_TAG: // 開始解析元素
				if ("person".equals(parser.getName())) {
					int id = Integer.valueOf(parser.getAttributeValue(0));
					person = new Person();
					person.setId(id);
				}
				if (person != null) {
					if ("name".equals(parser.getName())) {
						person.setName(parser.nextText());
					} else if ("age".equals(parser.getName())) {
						person.setAge(new Short(parser.nextText()));
					} else if ("sex".equals(parser.getName())) {
						person.setSex(parser.nextText());
					}
				}
				break;
			case XmlPullParser.END_TAG: // 結束元素
				if ("person".equals(parser.getName())) {
					list.add(person);
					person = null;
				}
				break;
			default:
				break;
			}
			event = parser.next();
		}
		return list;
	}
}
           

Pull解析器的運作方式與SAX解析器類似,都是事件驅動,有開始、結束事件,parser.next()可進入下一個事件

測試代碼

public void testPULLGetPersons() throws Exception {
		InputStream is = getContext().getResources().getAssets()
				.open("file.xml");
		List<Person> list = PULLHandler.getPersons(is);
		for (Person person : list) {
			GlobalConstants.PrintLog_D("[SAXTest]->testPULLGetPersons"
					+ person.toString());
		}
	}
           

測試結果

Android網絡下解析XML

三、使用DOM解析XML

package com.dzt.xml_parser;

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

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.dzt.xml_parser.domain.Person;

public class DOMHandler {
	public static List<Person> getPersons(InputStream is) throws Exception {
		List<Person> list = new ArrayList<Person>();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(is);
		Element root = document.getDocumentElement();
		NodeList nodeList = root.getElementsByTagName("person");
		for (int i = 0; i < nodeList.getLength(); i++) {
			Element element = (Element) nodeList.item(i);
			int id = Integer.valueOf(element.getAttribute("id"));
			Person person = new Person();
			person.setId(id);
			NodeList childList = element.getChildNodes();
			// 每個節點有多少個元素,周遊
			for (int j = 0; j < childList.getLength(); j++) {
				if (childList.item(j).getNodeType() == Node.ELEMENT_NODE) {
					if ("name".equals(childList.item(j).getNodeName())) {
						String name = childList.item(j).getFirstChild()
								.getNodeValue();
						person.setName(name);
					} else if ("age".equals(childList.item(j).getNodeName())) {
						String age = childList.item(j).getFirstChild()
								.getNodeValue();
						person.setAge(new Short(age));
					} else if ("sex".equals(childList.item(j).getNodeName())) {
						String sex = childList.item(j).getFirstChild()
								.getNodeValue();
						person.setSex(sex);
					}
				}
			}
			list.add(person);
		}
		is.close();
		return list;
	}
}
           

DOM是一種用于XML文檔的對象模型,用于直接通路XML文檔的各個部分,DOM被模拟成樹狀

Android網絡下解析XML

測試代碼

public void testDOMGetPersons() throws Exception {
		InputStream is = getContext().getResources().getAssets()
				.open("file.xml");
		List<Person> list = DOMHandler.getPersons(is);
		for (Person person : list) {
			GlobalConstants.PrintLog_D("[SAXTest]->testDOMGetPersons"
					+ person.toString());
		}
	}
           

測試結果

Android網絡下解析XML

完整Demo下載下傳:http://download.csdn.net/detail/deng0zhaotai/7422321