原帖地址:http://blog.163.com/liyinhui20080527@126/blog/static/815232582012114115014900/
SAX是Simple API for XML的缩写,它并不是由W3C官方所提出的标准。SAX是一种轻量型的方法,不像DOM解析时,把XML文档全部载入内存中,在PC上操作,Dom还有优势,但在手机中端上则无优势,因为手机内存和硬件都比不上PC强。使用 SAX 是比较安全的,并且 Android 提供了一种传统的 SAX 使用方法,以及一个便捷的 SAX 包装器。SAX采用基于事件驱动的处理方式,它将XML文档转换成一系列的事件,由单独的事件处理器来决定如何处理。
在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parser()方法来解析XML文档,并根据文档的内容产生事件。而事件处理器则是org.xml.sax包中的ContentHander、DTDHander、ErrorHandler,以及EntityResolver这4个接口,它们分别处理事件源在解析XML文档过程中产生的不同种类的事件。在开发中没有必要直接从这4个接口直接继承,因为org.xml.sax.helper包提供了类DefaultHandler,其继承了这4个接口,在实际开发中直接从DefaultHandler继承并实现相关函数就可以了。
如果定制,则还需要重写这几个方法。
1.开始解析
- public void startDocument()
2.结束解析
- public void endDocument()
3.遇到元素
- public void startElement(String namespaceURI, String localName,
- String qName, Attributes atts)
4.遇到元素
- public void endElement(String namespaceURI, String localName, String qName)
5. 与 之间
- public void characters(char ch[], int start, int length)
实例:
下面来看一个例子,首先创建一个服务器,此处通过JavaWeb里面的Servlet技术创建了一个返回XML的Web服务器,作为SAX解析的对象。Servlet部分程序属于JavaWeb基础部分,此处不讲解。创建的Web服务器返回的XML数据如图10-45所示。
![]() |
图10-45 Web服务器返回XML数据 |
Web服务器创建后,就可以在Android客户端开始解析XML了。解析前,先创建与XML属性对应的Bean实体类Person,该类中的属性和XML属性一一对应,也可以再对属性创建get和set方法,代码来源EX_10_06:
- public class Person {
- private String id;
- private String name;
- private String age;
- private String address;
- //省略get和set方法
- }
正式解析部分代码如下:
- …………………………………..省略导包部分代码…………………………………
- public class SAXXmlService extends DefaultHandler {
- // //定义一个Person引用
- Person person = null;
- // 此处将XML里的数据封装成Person类,personList用于装解析后的数据
- ArrayList<Person> personArr = null;
- // 定义一个标记变量,标记当前的XML文件被解析到哪个标签
- private String currentTag = null;
- /**
- * 执行解析
- *
- * @param queryString
- * @return
- * @throws Exception
- */
- public static ArrayList<Person> getPersonInfos(String queryString)
- throws Exception {
- // 得到SAX解析工厂
- SAXParserFactory factory = SAXParserFactory.newInstance();
- // 创建解析器
- SAXParser parser = factory.newSAXParser();
- XMLReader xmlreader = parser.getXMLReader();
- // 得到输入流
- URL url = new URL(queryString);
- InputSource is = new InputSource(url.openStream());
- // 得到SAX解析实现类
- SAXXmlService handler = new SAXXmlService();
- xmlreader.setContentHandler(handler);
- // 开始解析
- xmlreader.parse(is);
- return handler.personArr;
- }
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- super.characters(ch, start, length);
- // 判断当前标签是否有效
- if (currentTag != null) {
- // //读取标签里面的内容
- String value = new String(ch, start, length);
- // 如果是Id标签,则读取Id标签的内容设置到Person的ID值上
- if ("id".equalsIgnoreCase(currentTag)) {
- person.setId(value);
- } else if ("name".equalsIgnoreCase(currentTag)) {// name标签
- person.setName(value);
- } else if ("age".equalsIgnoreCase(currentTag)) {// age标签
- person.setAge(value);
- } else if ("address".equalsIgnoreCase(currentTag)) {// address标签
- person.setAddress(value);
- }
- }
- }
- /**
- * 解析XML时,当读到结束一个元素标签时
- */
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- super.endElement(uri, localName, qName);
- // 将当前标签名置空
- currentTag = null;
- // 如果当前结束的标签名是person的话,代表一个person对象已经读取完毕。将其添加到list后置空
- if (localName.equals("person")) {
- personArr.add(person);
- person = null;
- }
- }
- /**
- * 解析XML时,当开始读取XML文档时
- */
- @Override
- public void startDocument() throws SAXException {
- super.startDocument();
- personArr = new ArrayList<Person>();
- }
- /**
- * 解析XML时,当开始读到一个元素标签开始时
- */
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
- super.startElement(uri, localName, qName, attributes);
- if (localName.equals("person")) {
- person = new Person();
- }
- currentTag = localName;
- }
- }
解析代码中特别注意characters(char[] ch, int start, int length)方法的重写和维护currentTag的赋值和置空,其他地方都很好理解。
通过Activity显示到手机屏幕上,Activity代码如下,代码来源EX_10_06:
Activity中代码好理解,只是把XML解析出来组装成List对象,循环List再组装成字符串,然后再setText到TextView中。通过解析和显示,得到结果如图10-46所示。
- …………………………………..省略导包部分代码…………………………………
- public class SAXXmlActivityextends Activity {
- public static ArrayList<Person> objs = null;// 所有人员信息
- static final String queryString =
- "http://172.30.40.122:8080/exa_05/xmlServlet";//注意路径中如果是本机IP要写局域网地址
- TextView textView=null;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- textView=(TextView)this.findViewById(R.id.textView);
- StringBuffer sb=new StringBuffer();
- try {
- //调用解析XML服务
- objs = SAXXmlService.getPersonInfos(queryString);
- if(objs!=null&&objs.size()>0){
- //循环并组装字符串
- for(Person person:objs){
- sb.append("编号:"+person.getId()+"\n");
- sb.append("姓名:"+person.getName()+"\n");
- sb.append("年龄:"+person.getAge()+"\n");
- sb.append("地址:"+person.getAddress()+"\n");
- sb.append("\n");
- }
- }
- //显示组装字符串到页面上
- textView.setText(sb.toString());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
SAX读取XML文档的方法,占用内存比较少,但是开发流程相比DOM就复杂多了,具体采用哪种方法比较合适,大家可以在开发的过程中来深刻体会它们之间的差别。
![]()
图10-46 客户端解析图
- public void characters(char ch[], int start, int length)
实例:
下面来看一个例子,首先创建一个服务器,此处通过JavaWeb里面的Servlet技术创建了一个返回XML的Web服务器,作为SAX解析的对象。Servlet部分程序属于JavaWeb基础部分,此处不讲解。创建的Web服务器返回的XML数据如图10-45所示。
![]() |
图10-45 Web服务器返回XML数据 |
Web服务器创建后,就可以在Android客户端开始解析XML了。解析前,先创建与XML属性对应的Bean实体类Person,该类中的属性和XML属性一一对应,也可以再对属性创建get和set方法,代码来源EX_10_06:
- public class Person {
- private String id;
- private String name;
- private String age;
- private String address;
- //省略get和set方法
- }
正式解析部分代码如下:
- …………………………………..省略导包部分代码…………………………………
- public class SAXXmlService extends DefaultHandler {
- // //定义一个Person引用
- Person person = null;
- // 此处将XML里的数据封装成Person类,personList用于装解析后的数据
- ArrayList<Person> personArr = null;
- // 定义一个标记变量,标记当前的XML文件被解析到哪个标签
- private String currentTag = null;
- /**
- * 执行解析
- *
- * @param queryString
- * @return
- * @throws Exception
- */
- public static ArrayList<Person> getPersonInfos(String queryString)
- throws Exception {
- // 得到SAX解析工厂
- SAXParserFactory factory = SAXParserFactory.newInstance();
- // 创建解析器
- SAXParser parser = factory.newSAXParser();
- XMLReader xmlreader = parser.getXMLReader();
- // 得到输入流
- URL url = new URL(queryString);
- InputSource is = new InputSource(url.openStream());
- // 得到SAX解析实现类
- SAXXmlService handler = new SAXXmlService();
- xmlreader.setContentHandler(handler);
- // 开始解析
- xmlreader.parse(is);
- return handler.personArr;
- }
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- super.characters(ch, start, length);
- // 判断当前标签是否有效
- if (currentTag != null) {
- // //读取标签里面的内容
- String value = new String(ch, start, length);
- // 如果是Id标签,则读取Id标签的内容设置到Person的ID值上
- if ("id".equalsIgnoreCase(currentTag)) {
- person.setId(value);
- } else if ("name".equalsIgnoreCase(currentTag)) {// name标签
- person.setName(value);
- } else if ("age".equalsIgnoreCase(currentTag)) {// age标签
- person.setAge(value);
- } else if ("address".equalsIgnoreCase(currentTag)) {// address标签
- person.setAddress(value);
- }
- }
- }
- /**
- * 解析XML时,当读到结束一个元素标签时
- */
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- super.endElement(uri, localName, qName);
- // 将当前标签名置空
- currentTag = null;
- // 如果当前结束的标签名是person的话,代表一个person对象已经读取完毕。将其添加到list后置空
- if (localName.equals("person")) {
- personArr.add(person);
- person = null;
- }
- }
- /**
- * 解析XML时,当开始读取XML文档时
- */
- @Override
- public void startDocument() throws SAXException {
- super.startDocument();
- personArr = new ArrayList<Person>();
- }
- /**
- * 解析XML时,当开始读到一个元素标签开始时
- */
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
- super.startElement(uri, localName, qName, attributes);
- if (localName.equals("person")) {
- person = new Person();
- }
- currentTag = localName;
- }
- }
解析代码中特别注意characters(char[] ch, int start, int length)方法的重写和维护currentTag的赋值和置空,其他地方都很好理解。
通过Activity显示到手机屏幕上,Activity代码如下,代码来源EX_10_06:
Activity中代码好理解,只是把XML解析出来组装成List对象,循环List再组装成字符串,然后再setText到TextView中。通过解析和显示,得到结果如图10-46所示。
- …………………………………..省略导包部分代码…………………………………
- public class SAXXmlActivityextends Activity {
- public static ArrayList<Person> objs = null;// 所有人员信息
- static final String queryString =
- "http://172.30.40.122:8080/exa_05/xmlServlet";//注意路径中如果是本机IP要写局域网地址
- TextView textView=null;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- textView=(TextView)this.findViewById(R.id.textView);
- StringBuffer sb=new StringBuffer();
- try {
- //调用解析XML服务
- objs = SAXXmlService.getPersonInfos(queryString);
- if(objs!=null&&objs.size()>0){
- //循环并组装字符串
- for(Person person:objs){
- sb.append("编号:"+person.getId()+"\n");
- sb.append("姓名:"+person.getName()+"\n");
- sb.append("年龄:"+person.getAge()+"\n");
- sb.append("地址:"+person.getAddress()+"\n");
- sb.append("\n");
- }
- }
- //显示组装字符串到页面上
- textView.setText(sb.toString());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
SAX读取XML文档的方法,占用内存比较少,但是开发流程相比DOM就复杂多了,具体采用哪种方法比较合适,大家可以在开发的过程中来深刻体会它们之间的差别。
![]()
图10-46 客户端解析图