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适用于小型文档,随机访问,需要对文档进行修改。
下面看下在代码中是如何使用的
程序目录结构
需要解析的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);
}
}
它是以事件触发,一个节点一个节点去解析
对代码进行单元测试
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());
}
}
测试结果
二、使用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());
}
}
测试结果
三、使用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被模拟成树状
测试代码
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());
}
}
测试结果