SAX全称simple API for XML,同DOM一样也是一个访问XML文档的接口。SAX并不是一个实际可以直接对XML进行解析的解析器,而是他兼容SAX的解析器要实现的接口帮助类的集合。实现了SAX的解析器有很多,如Apache的Xerces,Oracle的XML Parser等。当然在Android中也支持SAX来解析XML,在Android的jar文件包中可以看到两个和SAX相关的包,它们分别是org.xml.sax和org.xml.sax.helper。

解析XML可以采用DOM进行解析,也可以采用SAX进行解析,SAX的设计事先与DOM是完全不同的。DOM处理XML文档是基于将XML文档解析成树状模型,放入内存中进行处理。而SAX则是采用基于事件驱动的处理模式,它将XML文档转化成一系列的事件,由单独的事件处理器来决定如何处理。当然各有各的好处,根据情况不同,而采用不同的解析方式。

DOM(文件对象模型),为XML文档的解析定义了一组接口。解析器读入整个文档,然后构建一个留驻内存的树结构,然后代码就可以使用DOM接口来操作整个树结构。

优点:整个文档树在内存当中,便于操作,支持删除、修改、重新排列等多种功能。

缺点:将整个文档调入内存,包过大量的无用的节点,延长了时间,过多占用了内存空间。

使用场合:一旦解析了文档还需多次访问这些数据、对硬件方面内存CPU有一定的要求。

为了解决DOM解析引起的的这些问题,出现了SAX。当解析器开始发现元素、解析结束,文本、文档的开始或者结束时,发送事件,我们编写响应这些事件的代码。

优点:不用事先调入整个文档,占用资源少。尤其在嵌入式环境,如Android,极力推荐采用SAX进行解析。

缺点:不像DOM一样将文档树长期留驻在内存,数据不是长久的。事件过后,若没保存数据,那么数据就会丢失。

使用场合:机器有性能限制,尤其是在嵌入式环境。

基于事件的处理模式主要是围绕着事件源以及事件处理器或叫监听器来工作的。一个可以产生时间的对象被称为事件源,而可以针对事件产生相应的对象就被叫做事件处理器。事件源和事件处理器是通过在事件中注册方法链接的。这样当事件源产生后,调用事件处理器相应的处理方法,一个事件就获得了处理。当然在事件源调用事件处理器中特定方法时会传递给事件处理器相应事件状态信息,这样事件处理器才能够根据事件信息来决定自己的行为。

在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parse()方法来开始解析XML文档,并根据文档内容产生事件。而事件处理器则是org.xml.sax包中的ContentHandler,DTDHandler,ErrorHandler,以及EntityResolver这个接口。它们分别处理事件源在解析过程中产生不同种类的事件(其中DTDHandler是为解析文档DTD时而用的)。而事件源XMLReader和这四个事件处理器的连接是通过在XMLReader中的相应事件处理器注册方法set来完成的。最常用的是setContentHandler。

处理器名称: 处理事件: 注册方法:

org.xml.sax.ContentHandler 跟文档相关的所有事件如: XMLReader中setContentHandler(ContentHandler handler)

文档的开始和结束、 元素的开始和结束 、可忽略的实体

名称空间前缀映射开始和结束 、 处理指令、字符数据和空格

org.xml.saxErrorHandler 处理XML文档解析时产生的错误。 setErrorHandler(ErrorHandler handler)

org.xml.sax.DTDHandler 处理对文档DTD进行解析时产生的相应事件 setDTDHandler(DTDHandler handler)

org.xml.sax.EntityResolver 处理外部实体 setEntityResolver(EntityResolver resolver)

ContentHandler接口中的方法说明

方法名 方法说明:

public void setDocumentLocator(Locator locator) 设置一个可以定位文档内容事件发生位置的定位器对象

public void startDocument()throws SAXException 用于处理文档解析开始事件

public void endDocument()throws SAXException 用于处理文档解析结束事件

public void startElement(java.lang.String namespaceURI, 处理元素开始时间,从参数中可以获得元素所在的名称空间的uri,元素名称,属性列表等信息

java.lang.String localName,java.lang.String qName

Attributes atts)throws SAXException

public void endElement(java.lang.String namespaceURI, 处理元素结束事件,从参数中可以获得元素所在名称空间的uri,元素名称等信息

java.lang.String localName,java.lang.String qName)

throws SAXException

public void characters(char[] ch,int start,int length) 处理元素的字符内容,从参数中可以获得内容

throws SAXException

org.xml.sax.XMLReader中的方法

public void setContentHandler(ContentHandler handler) 注册处理XML文档内容解析事件的ContentHandler

public void parse(InputSource input)

throws java.IOException,SAXException 开始解析一个XML文档

由于工作需要用心学习了一下Android系统自带的SAX针对xml的解析方法,参考网上的资料自己写个小例子!

建个项目名为SaxActivity源代码如下:

view source print ?
001 package com.sax.demo;
002
003 import java.io.InputStream;
004 import java.util.ArrayList;
005
006 import javax.xml.parsers.SAXParser;
007 import javax.xml.parsers.SAXParserFactory;
008
009 import org.xml.sax.Attributes;
010 import org.xml.sax.InputSource;
011 import org.xml.sax.XMLReader;
012
013 import android.app.Activity;
014 import android.os.Bundle;
015 import android.sax.Element;
016 import android.sax.EndElementListener;
017 import android.sax.EndTextElementListener;
018 import android.sax.RootElement;
019 import android.sax.StartElementListener;
020 import android.util.Log;
021 import android.widget.TextView;
022 /**
023 *
024 * @author Administrator
025 *@description 使用android系统自带的sax包进行XML解析
026 */
027 public class SaxActivity extends Activity {
028 private String result = "会员信息:\n";
029 private ArrayList<Person> PersonList = new ArrayList<Person>();
030 private Person person = null ;
031 public void onCreate(Bundle savedInstanceState) {
032 super.onCreate(savedInstanceState);
033 setContentView(R.layout.main);
034 try {
035 Log.i("通知", "开始解析");
036 InputStream inputStream = this.getClassLoader().getResourceAsStream("PersonDetail.xml");
037 SAXParserFactory factory = SAXParserFactory.newInstance();
038 SAXParser parser = factory.newSAXParser();
039 XMLReader reader = parser.getXMLReader();
040 reader.setContentHandler(getRootElement().getContentHandler());
041 reader.parse(new InputSource(inputStream));
042 Log.i("通知", "解析完毕");
043 }catch (Exception e) {
044 e.printStackTrace();
045 }
046 for(Person person:PersonList){
047 result += person.toString() + "\n";
048 }
049 TextView textView = (TextView)findViewById(R.id.textView);
050 textView.setText(result);
051 }
052 /**
053 *
054 * @return 返回设置好处理机制的rootElement
055 */
056 private RootElement getRootElement(){
057 /*rootElement代表着根节点,参数为根节点的TAGName*/
058 RootElement rootElement = new RootElement("PersonDetail");
059 /*获取一类子节点,并为其设置相应的事件
060 * 这里需要注意,虽然我们只设置了一次person的事件,但是我们文档中根节点下的所有
061 * person却都可以触发这个事件。
062 * */
063 Element personElement = rootElement.getChild("person");
064 // 读到元素开始位置时触发,如读到<person>时
065 personElement.setStartElementListener(new StartElementListener() {
066 @Override
067 public void start(Attributes attributes) {
068 // TODO Auto-generated method stub
069 Log.i("通知", "start");
070 person = new Person();
071 }
072 });
073 //读到元素结束位置时触发,如读到</person>时
074 personElement.setEndElementListener(new EndElementListener() {
075 @Override
076 public void end() {
077 PersonList.add(person);
078 }
079 });
080
081 Element nameElement = personElement.getChild("name");
082 // 读到文本的末尾时触发,这里的vip即为文本的内容部分
083 nameElement.setEndTextElementListener(new EndTextElementListener() {
084 @Override
085 public void end(String vip) {
086 person.setName(vip);
087 }
088 });
089
090 Element ageElement = personElement.getChild("age");
091 ageElement.setEndTextElementListener(new EndTextElementListener() {
092 @Override
093 public void end(String vip) {
094 person.setAge(vip);
095 }
096 });
097 Element jobElement = personElement.getChild("job");
098 jobElement.setEndTextElementListener(new EndTextElementListener() {
099 @Override
100 public void end(String vip) {
101 person.setJob(vip);
102 }
103 });
104 return rootElement;
105 }
106 private class Person {
107 String name;
108 String age;
109 String job;
110 public String getName() {
111 return name;
112 }
113 public void setName(String name) {
114 this.name = name;
115 }
116 public String getAge() {
117 return age;
118 }
119 public void setAge(String age) {
120 this.age = age;
121 }
122 public String getJob() {
123 return job;
124 }
125 public void setJob(String job) {
126 this.job = job;
127 }
128 @Override
129 public String toString() {
130 return "会员详细资料:年龄=" + age + ", 姓名=" + name + ", 工作=" + job + " ";
131 }
132 }
133 }
view source print ?
1 布局main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/textView" android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>

PersonDetail.xml文件存在src文件夹中代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<PersonDetail>
<person>
<name>李明</name>
<age>25</age>
<job>业务员</job>
</person>
<person>
<name>刘洋</name>
<age>34</age>
<job>医生</job>
</person>
</PersonDetail>

运行效果如图

更多相关文章

  1. android输入法02:openwnn源码解析01—输入流程
  2. Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流
  3. 【Android基础】讲讲Android的事件分发机制
  4. AndroidUI设计之 布局管理器 - 详细解析布局实现
  5. Android事件分发机制
  6. Android(安卓)Sensor Development
  7. 移动Android开发-规范文档
  8. 为Android应用程序读取/dev下设备而提权(二)
  9. Android(安卓)RxJava:图文详解 变换操作符

随机推荐

  1. android中的震动
  2. Android网络电台的一种实现方案(歌醉原创)
  3. Android(安卓)EditText无边框问题
  4. android 开发:使用SwipeRefreshLayout实现
  5. 安卓自动化测试第二课
  6. android EditText 如何限制只能输入指定
  7. Android(安卓)Launcher label和Main Acti
  8. mono for android生成APK出现错误fatal e
  9. android 饼图
  10. Android布局图标中心化