2.1 SAX
SAX(Simple API for XML)
使用流式处理的方式,它并不记录所读内容的相关信息。
它是一种以事件为驱动的XML API,解析速度快,占用内存少。使用回调函数来实现。
缺点是不能倒退。
2.2 DOM
DOM(Document Object Model)
是一种用于XML文档的对象模型,可用于直接访问 XML 文档的各个部分。
它是一次性全部将内容加载在内存中,生成一个树状结构,它没有涉及回调和复杂的状态管理。
缺点是加载大文档时效率低下。
2.3 PULL
Pull
内置于 Android 系统中。也是官方解析布局文件所使用的方式。
Pull 与 SAX 有点类似,都提供了类似的事件,如开始元素和结束元素。
不同的是,SAX 的事件驱动是回调相应方法,需要提供回调的方法,而后在 SAX 内部自动调用相应的方法。
而Pull解析器并没有强制要求提供触发的方法。因为他触发的事件不是一个方法,而是一个数字。它使用方便,效率高。
三、比较
SAX、DOM、Pull 的比较:
内存占用:SAX、Pull比DOM要好;
编程方式:SAX 采用事件驱动,在相应事件触发的时候,会调用用户编好的方法,也即每解析一类 XML,就要编写一个新的适合该类XML的处理类。DOM 是 W3C 的规范,Pull 简洁。
访问与修改:SAX 采用流式解析,DOM 随机访问。
访问方式:SAX,Pull 解析的方式是同步的,DOM 逐字逐句。
四、使用举例
- <?xml version="1.0" encoding="UTF-8"?>
- <persons>
- <person id="23">
- <name>李明</name>
- <age>30</age>
- </person>
- <person id="20">
- <name>李向梅</name>
- <age>25</age>
- </person>
- </persons>
4.1 SAX 解析举例
- public static List<Person> readXML(InputStream inStream) {
- try {
- //创建解析器
- SAXParserFactory spf = SAXParserFactory.newInstance();
- SAXParser saxParser = spf.newSAXParser();
- //设置解析器的相关特性,true表示开启命名空间特性
- saxParser.setProperty("http://xml.org/sax/features/namespaces",true);
- XMLContentHandler handler = new XMLContentHandler();
- saxParser.parse(inStream, handler);
- inStream.close();
- return handler.getPersons();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- //SAX类:DefaultHandler,它实现了ContentHandler接口。在实现的时候,只需要继承该类,重载相应的方法即可。
- public class XMLContentHandler extends DefaultHandler {
- private List<Person> persons = null;
- private Person currentPerson;
- private String tagName = null;//当前解析的元素标签
- public List<Person> getPersons() {
- return persons;
- }
- //接收文档开始的通知。当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
- @Override
- public void startDocument() throws SAXException {
- persons = new ArrayList<Person>();
- }
- //接收元素开始的通知。当读到一个开始标签的时候,会触发这个方法。其中namespaceURI表示元素的命名空间;
- //localName表示元素的本地名称(不带前缀);qName表示元素的限定名(带前缀);atts 表示元素的属性集合
- @Override
- public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
- if(localName.equals("person")){
- currentPerson = new Person();
- currentPerson.setId(Integer.parseInt(atts.getValue("id")));
- }
- this.tagName = localName;
- }
- //接收字符数据的通知。该方法用来处理在XML文件中读到的内容,第一个参数用于存放文件的内容,
- //后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
- @Override
- public void characters(char[] ch, int start, int length) throws SAXException {
- if(tagName!=null){
- String data = new String(ch, start, length);
- if(tagName.equals("name")){
- this.currentPerson.setName(data);
- }else if(tagName.equals("age")){
- this.currentPerson.setAge(Short.parseShort(data));
- }
- }
- }
- //接收文档的结尾的通知。在遇到结束标签的时候,调用这个方法。其中,uri表示元素的命名空间;
- //localName表示元素的本地名称(不带前缀);name表示元素的限定名(带前缀)
- @Override
- public void endElement(String uri, String localName, String name) throws SAXException {
- if(localName.equals("person")){
- persons.add(currentPerson);
- currentPerson = null;
- }
- this.tagName = null;
- }
- }
4.2 DOM 解析举例
public class DomPersonService {
/**
* @param inStream
* @return
* @throws Exception
*/
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;
}
}
public void testDOMGetPersons() throws Throwable {
InputStream inStream = this.getClass().getClassLoader()
.getResourceAsStream("person.xml");
List<Person> persons = DomPersonService.getPersons(inStream);
for (Person person : persons) {
Log.i(TAG, person.toString());
}
}
4.3 PULL解析举例
public class PullPersonService {
/**
* ------------------------使用PULL解析XML-----------------------
* @param inStream
* @return
* @throws Exception
*/
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;
}
}
public void testPullGetPersons() throws Throwable {
InputStream inStream = this.getClass().getClassLoader()
.getResourceAsStream("person.xml");
List<Person> persons = PullPersonService.getPersons(inStream);
for (Person person : persons) {
Log.i(TAG, person.toString());
}
}