XML解析

现在在android平台上可以有三种对xml文件的解析方式,分别是DOM、SAX、PULL,他们各有有优缺点,如下:

1 Dom解析是将xml文件全部载入,组装成一颗dom树,然后通过节点以及节点之间的关系来解析xml文件;从全部载入这点可知这种方式比较消耗内存。

DOM是文档对象模型解析,构建文档的分层语法结构,在内存中建立DOM树,DOM树的节点以对象的形式来标识,文档解析文成以后,文档的整个DOM树都会放在内存中。

2 SAX解析器是基于事件处理的,需要从头到尾把XML文档扫描一遍,在扫描的过程中,每次遇到一个语法结构时,就会调用这个特定语法结构的事件处理程序,向应用程序发送一个事件。

3 PULL解析器的运行方式和SAX解析器很相似,它提供了类似的事件,如:开始元素和结束元素,使用parser,next() 可以进入下一个元素并且触发相应的事件,事件将作为代码被发送,因此可以使用一个switch来对事件进行选择,然后进行相应的处理。当开始解析元素的时候,调用parser.nextText()方法可以获得下一个Text类型的元素。
相对而言,使用PULL来解析比SAX要写的代码少很多,使用比较简单。
PULL的特点:
1)、简单的结构:一个接口、一个例外、一个工厂组成的PULL解析器
2)、简单易用:PULL解析器只有一个重要的方法next方法,他被用来检索下一个事件,而它只有5个常用的属性:
          1、STARTDOCUMENT
          2、START_TAG
          3、TEXT
          4、END_TAG
          5、END_DOCUMENT

下面结合实例来理解上面的理论知识:

1 要解析的xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<persons>
	<person id = "23">
		<name>NEwii</name>
		<age>21</age>
	</person>
	<person id = "20">
		<name>WiiWill</name>
		<age>25</age>
	</person>
</persons>

解析方式:

1 DOM解析

	public void testDOMgetPersons() throws Throwable{
		InputStream inStream = this.getClass().getClassLoader().
				getResourceAsStream("wangjialin.xml");
		List<Person> persons = DOMPersonService.getPersons(inStream);
		for(Person person : persons){
			Log.i(TAG, person.toString());
		}
	}
下面是具体的DOM解析类DOMPersonService.java

package com.wangjialin.service;

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.wangjialin.domain.Person;

public class DOMPersonService {
	public static List<Person> getPersons(InputStream inStream) throws Exception{
		List<Person> persons = new ArrayList<Person>();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(inStream);
		Element root = document.getDocumentElement();
		NodeList personNodes = root.getElementsByTagName("person");
		for(int i=0; i < personNodes.getLength() ; i++){
			Element personElement = (Element)personNodes.item(i);
			int id = new Integer(personElement.getAttribute("id"));
			Person person = new Person();
			person.setId(id);
			NodeList childNodes = personElement.getChildNodes();
			for(int y=0; y < childNodes.getLength() ; y++){
				if(childNodes.item(y).getNodeType()==Node.ELEMENT_NODE){
					if("name".equals(childNodes.item(y).getNodeName())){
						String name = childNodes.item(y).getFirstChild().getNodeValue();
						person.setName(name);
					}else if("age".equals(childNodes.item(y).getNodeName())){
						String age = childNodes.item(y).getFirstChild().getNodeValue();
						person.setAge(new Short(age));
					}
				}
			}
			persons.add(person);
		}
		inStream.close();
		return persons;
	}
}
2 SAX解析
	public void testSAXGetPersons() throws Throwable{
		InputStream inputStream = this.getClass().getClassLoader().
				getResourceAsStream("wangjialin.xml");
		SAXForHandler saxForHandler = new SAXForHandler();
		SAXParserFactory spf = SAXParserFactory.newInstance();
    	SAXParser saxParser = spf.newSAXParser();
    	saxParser.parse(inputStream, saxForHandler);
    	List<Person> persons = saxForHandler.getPersons();
    	inputStream.close();
    	for(Person person:persons){
    		Log.i(TAG, person.toString());
    	}
	}
下面是事件处理类SAXForHandler.java
package com.wangjialin.service;

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.util.Log;

import com.wangjialin.domain.Person;

public class SAXForHandler extends DefaultHandler {
	private static final String TAG = "SAXForHandler"; 
	private List<Person> persons;
	private String perTag ;//通过此变量,记录前一个标签的名称。
	Person person;//记录当前Person
	
	public List<Person> getPersons() {
		return persons;
	}

	//适合在此事件中触发初始化行为。
	public void startDocument() throws SAXException {
		persons = new ArrayList<Person>();
		Log.i(TAG , "***startDocument()***");
	}

	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		if("person".equals(localName)){
			for ( int i = 0; i < attributes.getLength(); i++ ) {
				Log.i(TAG ,"attributeName:" + attributes.getLocalName(i)
						+ "_attribute_Value:" + attributes.getValue(i));
				person = new Person();
				person.setId(Integer.valueOf(attributes.getValue(i)));
			}
		}
		perTag = localName;
		Log.i(TAG , qName+"***startElement()***");
	}
	
	public void characters(char[] ch, int start, int length) throws SAXException {
		String data = new String(ch, start, length).trim();
	    if(!"".equals(data.trim())){
	           Log.i(TAG ,"content: " + data.trim());
	    }
	    if("name".equals(perTag)){
				person.setName(data);
		}else if("age".equals(perTag)){
				person.setAge(new Short(data));
		}
	}
	
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		Log.i(TAG , qName+"***endElement()***");
		if("person".equals(localName)){
			persons.add(person);
			person = null;
		}
		perTag = null;
	}

	public void endDocument() throws SAXException {
		Log.i(TAG , "***endDocument()***");
	}
}

3 PULL解析

下面是PULL解析客户端调用:

	public void testPullgetPersons() throws Throwable{
		InputStream inStream = this.getClass().getClassLoader().getResourceAsStream("wangjialin.xml");
		List<Person> persons = PullPersonService.getPersons(inStream);
		for(Person person : persons){
			Log.i(TAG, person.toString());
		}
	}
下面是使用PULL的方式保存person到XML文件的客户端调用:
	public void testSave() throws Throwable{
		File file = new File(this.getContext().getFilesDir(), "wangjialin.xml");
		FileOutputStream outStream = new FileOutputStream(file);
		List<Person> persons = new ArrayList<Person>();
		persons.add(new Person(90, "wangjialin", (short)13));
		persons.add(new Person(35, "jialingege", (short)23));
		persons.add(new Person(78, "Android", (short)33));
		PullPersonService.save(persons, outStream);
	}

以下是实现PULL解析及使用PULL的方式保存对象到xml文件的实现类:
package com.wangjialin.service;

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

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;

import android.util.Xml;

import com.wangjialin.domain.Person;

public class PullPersonService {
	public static void save(List<Person> persons, OutputStream outStream) throws Exception{
		XmlSerializer serializer = Xml.newSerializer();
		serializer.setOutput(outStream, "UTF-8");
		serializer.startDocument("UTF-8", true);
		serializer.startTag(null, "persons");
		for(Person person : persons){
			serializer.startTag(null, "person");
			serializer.attribute(null, "id", person.getId().toString());
			serializer.startTag(null, "name");
			serializer.text(person.getName());
			serializer.endTag(null, "name");
			
			serializer.startTag(null, "age");
			serializer.text(person.getAge().toString());
			serializer.endTag(null, "age");
			
			serializer.endTag(null, "person");
		}		
		serializer.endTag(null, "persons");
		serializer.endDocument();
		outStream.flush();
		outStream.close();
	}

	public static List<Person> getPersons(InputStream inStream) throws Exception{
		Person person = null;
		List<Person> persons = null;
		XmlPullParser pullParser = Xml.newPullParser();
		pullParser.setInput(inStream, "UTF-8");
		int event = pullParser.getEventType();//触发第一个事件
		while(event!=XmlPullParser.END_DOCUMENT){
			switch (event) {
			case XmlPullParser.START_DOCUMENT:
				persons = new ArrayList<Person>();
				break;
			case XmlPullParser.START_TAG:
				if("person".equals(pullParser.getName())){
					int id = new Integer(pullParser.getAttributeValue(0));
					person = new Person();
					person.setId(id);
				}
				if(person!=null){
					if("name".equals(pullParser.getName())){
						person.setName(pullParser.nextText());
					}
					if("age".equals(pullParser.getName())){
						person.setAge(new Short(pullParser.nextText()));
					}
				}
				break;
				
			case XmlPullParser.END_TAG:
				if("person".equals(pullParser.getName())){
					persons.add(person);
					person = null;
				}
				break;
			}
			event = pullParser.next();
		}
		return persons;
	}
}

完整源代码工程


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值