android中xml中的sax pull解析
在Android平台上可以使用Simple API for XML(SAX) 、 Document Object Model(DOM)和Android附带的pull解析器解析XML文件。上面面是本例子要解析的XML文件:
文件名称:itcast.xml <?xml version="1.0" encoding="UTF-8"?><persons><person id="23"><name>liming</name><age>30</age></person><person id="20"><name>lixiangmei</name><age>25</age></person></persons>
例子定义了一个javabean用于存放上面解析出来的xml内容, 这个javabean为Person
package cn.itcast.domain;public class Person {private Integer id;private String name;private Short age;public Person(){}public Person(Integer id, String name, Short age) {this.id = id;this.name = name;this.age = 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;}@Overridepublic String toString() {return "Person [age=" + age + ", id=" + id + ", name=" + name + "]";}}
使用SAX读取XML文件
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)就可以获取内容。
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 cn.itcast.domain.Person;/** * 采用SAX解析XML内容 */public class SAXPersonService {public List<Person> getPersons(InputStream inStream) throws Throwable{SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser parser = factory.newSAXParser();PersonParser personParser = new PersonParser();parser.parse(inStream, personParser);inStream.close();return personParser.getPersons();}private final class PersonParser extends DefaultHandler{private List<Person> persons = null;private String tag = null;private Person person = null;public List<Person> getPersons() {return persons;}@Overridepublic void startDocument() throws SAXException {persons = new ArrayList<Person>();}@Overridepublic 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;}@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {if(tag!=null){String data = new String(ch, start, length);//获取文本节点的数据if("name".equals(tag)){person.setName(data);}else if("age".equals(tag)){person.setAge(new Short(data));}}}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {if("person".equals(localName)){persons.add(person);person = null;}tag = null;}}}
除了可以使用 SAX或DOM解析XML文件之外,大家也可以使用Android内置的Pull解析器解析XML文件。 Pull解析器是一个开源的java项目,既可以用于android,也可以用于JavaEE。如果用在javaEE需要把其jar文件放入类路径中,因为Android已经集成进了Pull解析器,所以无需添加任何jar文件。android系统本身使用到的各种xml文件,其内部也是采用Pull解析器进行解析的。 Pull解析器的运行方式与 SAX 解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。跟SAX不同的是, Pull解析器产生的事件是一个数字,而非方法,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型节点的值。
有些时候,我们需要生成一个XML文件,生成XML文件的方法有很多,如:可以只使用一个StringBuilder组拼XML内容,然后把内容写入到文件中;或者使用DOM API生成XML文件,或者也可以使用pull解析器生成XML文件,这里推荐大家使用Pull解析器解析和生成xml的代码如下
package cn.itcast.service;import java.io.InputStream;import java.io.OutputStream;import java.io.Writer;import java.util.ArrayList;import java.util.List;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlSerializer;import android.util.Xml;import cn.itcast.domain.Person;/** * 采用Pull解析XML内容 */public class PULLPersonService {public static void save(List<Person> persons, Writer writer) throws Throwable{XmlSerializer serializer = Xml.newSerializer();serializer.setOutput(writer);serializer.startDocument("UTF-8", true);serializer.startTag(null, "persons");for(Person person : persons){serializer.startTag(null, "person");serializer.attribute(null, "id", person.getId().toString());serializer.startTag(null, "name");serializer.text(person.getName());serializer.endTag(null, "name");serializer.startTag(null, "age");serializer.text(person.getAge().toString());serializer.endTag(null, "age");serializer.endTag(null, "person");}serializer.endTag(null, "persons");serializer.endDocument();writer.flush();writer.close();}public static List<Person> getPersons(InputStream inStream) throws Throwable{List<Person> persons = null;Person person = null;XmlPullParser parser = Xml.newPullParser();parser.setInput(inStream, "UTF-8");int eventType = parser.getEventType();//产生第一个事件while(eventType!=XmlPullParser.END_DOCUMENT){//只要不是文档结束事件switch (eventType) {case XmlPullParser.START_DOCUMENT:persons = new ArrayList<Person>();break;case XmlPullParser.START_TAG:String name = parser.getName();//获取解析器当前指向的元素的名称if("person".equals(name)){person = new Person();person.setId(new Integer(parser.getAttributeValue(0)));}if(person!=null){if("name".equals(name)){person.setName(parser.nextText());//获取解析器当前指向元素的下一个文本节点的值}if("age".equals(name)){person.setAge(new Short(parser.nextText()));}}break;case XmlPullParser.END_TAG:if("person".equals(parser.getName())){persons.add(person);person = null;}break;}eventType = parser.next();}return persons;}}测试代码
import java.io.BufferedWriter;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStreamWriter;import java.io.StringWriter;import java.util.ArrayList;import java.util.List;import cn.itcast.domain.Person;import cn.itcast.service.DOMPersonService;import cn.itcast.service.PULLPersonService;import cn.itcast.service.SAXPersonService;import android.content.Context;import android.test.AndroidTestCase;import android.util.Log;public class PersonServiceTest extends AndroidTestCase {private static final String TAG = "PersonServiceTest";public void testSAXGetPersons() throws Throwable{SAXPersonService service = new SAXPersonService();InputStream inStream = getClass().getClassLoader().getResourceAsStream("itcast.xml");List<Person> persons = service.getPersons(inStream);for(Person person : persons){Log.i(TAG, person.toString()); }}public void testDomGetPersons() throws Throwable{InputStream inStream = getClass().getClassLoader().getResourceAsStream("itcast.xml");List<Person> persons = DOMPersonService.getPersons(inStream);for(Person person : persons){Log.i(TAG, person.toString());}}public void testPullGetPersons() throws Throwable{InputStream inStream = getClass().getClassLoader().getResourceAsStream("itcast.xml");List<Person> persons = PULLPersonService.getPersons(inStream);for(Person person : persons){Log.i(TAG, person.toString());}}public void testSave() throws Throwable{//File file = new File(this.getContext().getFilesDir(), "person.xml");//FileOutputStream outStream = new FileOutputStream(file);List<Person> persons = new ArrayList<Person>();persons.add(new Person(34, "lili", (short)12));persons.add(new Person(56, "老毕", (short)32));persons.add(new Person(39, "老张", (short)40));/*FileOutputStream outStream = this.getContext().openFileOutput("person.xml", Context.MODE_PRIVATE);OutputStreamWriter writer = new OutputStreamWriter(outStream, "UTF-8");BufferedWriter bWriter = new BufferedWriter(writer);*/StringWriter writer = new StringWriter();PULLPersonService.save(persons, writer);Log.i(TAG, writer.toString());}}
更多相关文章
- andorid 将布局文件(layout)转换为图片(Bitmap)简单使用详解
- Android学习笔记-ProgressBar和ListView使用方法(二)
- Android getResources().getConfiguration()方法的作用
- Android 存储字符串数据到txt文件
- 如何简单修改Android的so文件
- EditText点击事件——弹出单选框
- 第三十六天 一乐在其中—Android的按钮单击事件及监听器的实现方
- Android视频文件格式解析相关分析