使用SAX读取XML文件

 

我们在学习JavaWEB基础时,老方有讲解使用JavaSE解析XML文件。我们在学习JavaEE时一般都使用dom4j解析XML文件。在Android中解析XMLJavaSEJavaEE都差不多,我们也可以在Andorid中使用dom4j,但这会占用系统的资源。

 Andorid中解析XML有三种技术SAXDOMpull,重点是Saxpull。尤其是pullAndroid推荐使用,Android系统自身就是使用pull来解析的。pull的解析速度和资源的占用可以与sax相媲美,但使用上比sax更简单。

 

SAX 是一个解析速度快并且占用内存少的 xml 解析器,非常适合用于 Android 等移动设备。 SAX 解析 XML 文件采用 的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中, SAX 会判断当前读到 的字符是否合法 XML 语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调( callback )方 法,这些方法 ( 事件 ) 定义在 ContentHandler 接口。下面是一些 ContentHandler 接口常用的方法:
startDocument()
当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
endDocument()
和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
startElement(String namespaceURI, String localName, String qName, Attributes atts)
当读到一个开始标签的时候,会触发这个方法。 namespaceURI 就是命名空间, localName 是不带命名空间前缀 的标签名, qName 是带命名空间前缀的标签名。通过 atts 可以得到所有的属性名和相应的值。要注意的是 SAX 一个重要的特点就是它 的流式处理 ,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说, startElement() 方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字, 是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。 这使得 SAX 在编程处理上 没有 DOM 来得那么方便。
endElement(String uri, String localName, String name)
这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
characters(char[] ch, int start, int length)
这个方法用来处理在 XML 文件中读到的内容,第一个参数用于存放文件的内容,后面两个参数是读到的字符串在 这个数组中的起始位置和长度,使用 new String(ch,start,length) 就可以获取内容。
l SAX 支持已内置到JDK1.5中,你无需添加任何的jar文件。
<?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>
解析 person.xml 触发的事件为:
读到的标签及内容        触发事件
{ 文档开始 }          startDocument()
<persons>           startElement (“”, "persons", null, "{Attributes}")
"\n\t"              characters("<persons>...</persons>", "12", "2")
<person>            startElement (“”, "person", null, "{Attributes}")
"\n\t\t"            characters("<persons>...</persons>", "31", "3")
<name>              startElement (“”, "name", null, "{Attributes}")
" 李明 "              characters("<persons>...</persons>", "40", "2")
</name>             endElement("", "name", null)
"\n\t\t"            characters("<persons>...</persons>", "50", "3")
<age>               startElement (“”, "age", null, "{Attributes}")
"30"                characters("<persons>...</persons>", "58", "2")
</age>              endElement("", "age", null)
"\n\t"              characters("<persons>...</persons>", "67", "2")
</person>           endElement("", "person", null)
"\n\t"              characters("<persons>...</persons>", "79", "2")
<person>            startElement (“”, "person", null, "{Attributes}")
"\n\t\t"            characters("<persons>...</persons>", "98", "3")
<name>              startElement (“”, "name", null, "{Attributes}")
" 李向梅 "            characters("<persons>...</persons>", "107", "3")
</name>             endElement("", "name", null)
"\n\t\t"            characters("<persons>...</persons>", "118", "3")
<age>               startElement (“”, "age", null, "{Attributes}")
"25"                characters("<persons>...</persons>", "126", "2")
</age>              endElement("", "age", null)
"\n\t"              characters("<persons>...</persons>", "135", "2")
</person>           endElement("", "person", null)
"\n"                characters("<persons>...</persons>", "147", "1")
</persons>          endElement("", "persons", null)
{ 文档结束 }          endDocument()

 1.创建Android工程(eclipse3.6)

       Project name:XML

       BuildTarget:Android2.2

       Application name:xml解析器

       Package name:com.changcheng.androidxml

       Create Activity:XMLActivity

       Min SDK Version:8

  2.需要解析的XML文件:person.xml

 

<?xml version="1.0" encoding="UTF-8"?>

<persons>

<person id="11">

<name>maozhuxi</name>

<age>55</age>

</person>

<person id="22">

<name>tiananmeng</name>

<age>66</age>

</person>

</persons>

         该文件存放于src源码目录。
 3.XML文件对应的实体Person
package com.jbridge.xml.domain;

public class Person {
private Integer id;
private String name;
private Short age;
public Integer getId() {
return id;
}
public void setId(Integer 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;
}
@Override
public String toString() {
return "Person [age=" + age + ", id=" + id + ", name=" + name + "]";
}
public Person(Integer id, String name, Short age) {
this.id = id;
this.name = name;
this.age = age;
}
public Person(){}

}
 4.Sax解析XML的事件处理类:
package com.jbridge.xml.service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.jbridge.xml.domain.Person;

public class SAXPersonService {
public List<Person> getSAXPersons(InputStream inStream) throws Exception{
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();//创建解析器
//设置解析器的相关特性,http://xml.org/sax/features/namespaces = true 表示开启命名空间特性,这个可以不写  
//saxParser.setProperty("http://xml.org/sax/features/namespaces",true);
PersonHandler handler = new PersonHandler();
parser.parse(inStream, handler);
inStream.close();
return handler.getPersons();
}
private final class PersonHandler extends DefaultHandler{
private List<Person> persons = null;
private Person person = null;
private String tag = 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 uri, String localName, String qName, Attributes attributes) throws SAXException {
if("person".equals(localName)){
person = new Person();
person.setId(new Integer(attributes.getValue(0)));
}
tag = localName;
}
   /**
         *      接收字符数据的通知。
         */
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if(tag!=null){
String textdata = new String(ch, start, length);
if("name".equals(tag)){
person.setName(textdata);
}else if("age".equals(tag)){
person.setAge(new Short(textdata));
}
}
}

        /**
         *      接收文档的结尾的通知。
         *     uri:元素的命名空间
         *     localName:元素的本地名称(不带前缀)
         *     name:元素的限定名(带前缀)
         */
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("person".equals(localName)){
persons.add(person);
person = null;
}
tag = null;
}
}

}
  5.编写测试Sax解析XML的类(测试要配置AndroidManifest.xml)
package com.jbridge.xml.activity;
 
import java.io.InputStream;
import java.util.List;

import com.jbridge.xml.domain.Person;
import com.jbridge.xml.service.SAXPersonService;

import android.test.AndroidTestCase;
import android.util.Log;

public class TestService extends AndroidTestCase {
private static final String TAG = "PersonServiceTest";

public void testGetSAXPersons() throws Exception {

InputStream inputStream = TestService.class.getClassLoader()
.getResourceAsStream("person.xml");
SAXPersonService saxPersonService = new SAXPersonService();
List<Person> persons = saxPersonService.getSAXPersons(inputStream);
inputStream.close();
for (Person person : persons) {
Log.i(TAG, person.toString());
}

}
}
  6.运行测试类
其他代码见附件。

 


你可能感兴趣的:(数据结构,编程,android,xml,javaee)