首先我们来了解一下SAX解析器的基本知识:
SAX(Simple API for XML)解析器是一种基于事件的解析器,事件驱动的流式解析方式是,从文件的开始顺序解析到文档的结束,不可暂停或倒退。它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。
SAX的工作原理:简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
然后我们通过一个小例子来看一下android中我们如何运用SAX去解析XML文件:
(1)首先我们拷贝一个beauties.xml文件到assets目录下,其内容如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beauties> 3 <beauty> 4 <name>范冰冰</name> 5 <age>28</age> 6 </beauty> 7 <beauty> 8 <name>杨幂</name> 9 <age>23</age> 10 </beauty> 11 12 </beauties>
(2) 然后在layout下面新建一个布局文件saxtest.xml,其内容如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:orientation="vertical" > 6 7 <TextView 8 android:id="@+id/textView" 9 android:layout_width="fill_parent" 10 android:layout_height="wrap_content" /> 11 12 </LinearLayout>
(3)在src目录下新建一个与xml里面的节点对应的一个类Beauty,内容如下:
1 package com.saxtest; 2 3 public class Beauty { 4 5 private String name; 6 private String age; 7 8 public String getName() { 9 return name; 10 } 11 12 public void setName(String name) { 13 this.name = name; 14 } 15 16 public String getAge() { 17 return age; 18 } 19 20 public void setAge(String age) { 21 this.age = age; 22 } 23 24 @Override 25 public String toString() { 26 return "美女资料 [年龄=" + age + ", 姓名=" + name + "]"; 27 } 28 }
再写一个关键的类MySaxHandler,在这个类中我们将解析出来的字符串生成了Beauty对象,并加入到List中,代码已经详细注释,内容如下:
1 package com.saxtest; 2 3 import java.util.ArrayList; 4 5 import org.xml.sax.Attributes; 6 import org.xml.sax.SAXException; 7 import org.xml.sax.helpers.DefaultHandler; 8 9 public class MySaxHandler extends DefaultHandler{ 10 11 //声明一个装载Beauty类型的List 12 private ArrayList<Beauty> mList; 13 //声明一个Beauty类型的变量 14 private Beauty beauty; 15 //声明一个字符串变量 16 private String content; 17 18 /** 19 * MySaxHandler的构造方法 20 * 21 * @param list 装载返回结果的List对象 22 */ 23 public MySaxHandler(ArrayList<Beauty> list){ 24 this.mList = list; 25 } 26 27 /** 28 * 当SAX解析器解析到XML文档开始时,会调用的方法 29 */ 30 @Override 31 public void startDocument() throws SAXException { 32 super.startDocument(); 33 } 34 35 /** 36 * 当SAX解析器解析到XML文档结束时,会调用的方法 37 */ 38 @Override 39 public void endDocument() throws SAXException { 40 super.endDocument(); 41 } 42 43 /** 44 * 当SAX解析器解析到某个属性值时,会调用的方法 45 * 其中参数ch记录了这个属性值的内容 46 */ 47 @Override 48 public void characters(char[] ch, int start, int length) 49 throws SAXException { 50 super.characters(ch, start, length); 51 content = new String(ch, start, length); 52 } 53 54 /** 55 * 当SAX解析器解析到某个元素开始时,会调用的方法 56 * 其中localName记录的是元素属性名 57 */ 58 @Override 59 public void startElement(String uri, String localName, String qName, 60 Attributes attributes) throws SAXException { 61 super.startElement(uri, localName, qName, attributes); 62 63 if("beauty".equals(localName)){ 64 beauty = new Beauty(); //新建Beauty对象 65 } 66 } 67 68 /** 69 * 当SAX解析器解析到某个元素结束时,会调用的方法 70 * 其中localName记录的是元素属性名 71 */ 72 @Override 73 public void endElement(String uri, String localName, String qName) 74 throws SAXException { 75 super.endElement(uri, localName, qName); 76 77 if("name".equals(localName)){ 78 beauty.setName(content); 79 }else if("age".equals(localName)){ 80 beauty.setAge(content); 81 }else if("beauty".equals(localName)){ 82 mList.add(beauty); //将Beauty对象加入到List中 83 } 84 } 85 }
第三个源文件就是SaxTestActivity,这个Activity的布局文件saxtest.xml,之前已经给出过它的内容,现在我们贴出Activity源码的内容,代码都已经详细注释了:
1 package com.saxtest; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 6 import javax.xml.parsers.SAXParser; 7 import javax.xml.parsers.SAXParserFactory; 8 9 import org.xml.sax.InputSource; 10 import org.xml.sax.XMLReader; 11 12 import android.app.Activity; 13 import android.content.res.AssetManager; 14 import android.os.Bundle; 15 import android.widget.TextView; 16 17 import com.example.saxtest.R; 18 19 public class SaxTestActivity extends Activity{ 20 21 //声明装载Beauty对象的List 22 private ArrayList<Beauty> beautyList; 23 24 @Override 25 protected void onCreate(Bundle savedInstanceState) { 26 super.onCreate(savedInstanceState); 27 setContentView(R.layout.saxtest); 28 29 //初始化beautyList链表 30 if(beautyList == null){ 31 beautyList = new ArrayList<Beauty>(); 32 } 33 34 doMyMission(); 35 36 setupViews(); 37 } 38 39 /** 40 * 使用SAX解析器解析XML文件的方法 41 */ 42 private void doMyMission(){ 43 try { 44 //获取AssetManager管理器对象 45 AssetManager as = this.getAssets(); 46 //通过AssetManager的open方法获取到beauties.xml文件的输入流 47 InputStream is = as.open("beauties.xml"); 48 //通过获取到的InputStream来得到InputSource实例 49 InputSource is2 = new InputSource(is); 50 //使用工厂方法初始化SAXParserFactory变量spf 51 SAXParserFactory spf = SAXParserFactory.newInstance(); 52 //通过SAXParserFactory得到SAXParser的实例 53 SAXParser sp = spf.newSAXParser(); 54 //通过SAXParser得到XMLReader的实例 55 XMLReader xr = sp.getXMLReader(); 56 //初始化自定义的类MySaxHandler的变量msh,将beautyList传递给它,以便装载数据 57 MySaxHandler msh = new MySaxHandler(beautyList); 58 //将对象msh传递给xr 59 xr.setContentHandler(msh); 60 //调用xr的parse方法解析输入流 61 xr.parse(is2); 62 } catch (Exception e) { 63 e.printStackTrace(); 64 } 65 } 66 67 /** 68 * 将解析结果输出到界面的方法 69 */ 70 private void setupViews(){ 71 String result = ""; 72 73 for (Beauty b : beautyList) { 74 result += b.toString(); 75 } 76 77 TextView textView = (TextView) findViewById(R.id.textView); 78 textView.setText(result); 79 } 80 81 }
右键运行工程代码,结果截图如下: