因为有些时候,应用的数据是采用XML文件的格式存放的,所以我们需要知道怎么从XML文件中读取这些数据
在Android中可以通过SAX、DOM、pull解析XML文件。
在本篇博文中主要介绍采用Pull解析器解析和生成XML内容。
介绍:在Android已经集成了Pull解析器,所以无需添加任何的jar文件。在Android中本身用到的各种xml文件,其内部也是采用Pull解析器进行解析的。
一、采用Pull解析器解析XML文件内容
首先,我们需要先建立一个Android Project项目,名称为:xml。默认生成MainActivity.java,在cn.itcast.xml包下,这个java文件里边的内容是自动生成的。
然后,我们在src目录下建立一个xml文件:person.xml:
<?xml version="1.0" encoding="UTF-8"?> <!-- 这个文件头是start document事件 -->
<persons>
<person id="1">
<name>zhangsan</name>
<age>30</age>
</person>
<person id="2">
<name>lisi</name>
<age>25</age>
</person>
</persons>
可以看出来这个xml文件存了两个person的信息。
接下来,我们需要建立一个javabean来反射这个xml文件,Person.java(注意这个bean中的属性要和xml中的对应,不然不能正确解析):
package cn.itcast.domain;
public class Person {
private Integer id;
private String name;
private Integer age;
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", 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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
在这个java文件中我们定义了三个属性:id、name、age,并生成了一个toString()的方法
在实体类建好之后,我们需要写业务层的类了,PersonService.java:
package cn.itcast.service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import cn.itcast.domain.*;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.util.Xml;
public class PersonService {
public static List<Person> getPersons(InputStream xml) throws Exception{
List<Person> persons = null;
Person person = null;
//得到解析器
/*这个方法和下边功能相同,可以得到解析器:XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser();*/
XmlPullParser pullParser = Xml.newPullParser();
pullParser.setInput(xml,"UTF-8");//为Pull解析器设置要解析的XML数据
int event = pullParser.getEventType(); //产生第一个事件:start document
while(event != XmlPullParser.END_DOCUMENT){
switch (event) { //对事件进行判断
case XmlPullParser.START_DOCUMENT:
persons = new ArrayList<Person>();
break;
case XmlPullParser.START_TAG:
if("person".equals(pullParser.getName())){
int id = new Integer(pullParser.getAttributeValue(0));
person = new Person();
person.setId(id);
}
if("name".equals(pullParser.getName())){
String name = pullParser.nextText();
person.setName(name);
}
if("age".equals(pullParser.getName())){
int age = new Integer(pullParser.nextText());
person.setAge(age);
}
break;
case XmlPullParser.END_TAG:
if("person".equals(pullParser.getName())){
persons.add(person);
person = null;
}
break;
}
event = pullParser.next();
}
return persons;
}
}
这段代码比较麻烦,我们接下来具体分析一下:
XmlPullParser pullParser = Xml.newPullParser();这段代码是为了得到一个Pull解析器,另外:XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser();也可以得到Pull解析器。
pullParser.setInput(xml,"UTF-8");用来设置要解析的xml文件的编码格式,这里是“UTF-8”
因为Pull解析器是一个遍历文档的过程,所以要从<?xml version="1.0" encoding="UTF-8"?>这个start document事件开始,一直到</persons>结束。
int event = pullParser.getEventType();在这个时候,文档被初始化,这里会获得文档的start document,就是START_DOCUMENT事件。
然后,是一个while循环,限制条件是event != XmlPullParser.END_DOCUMENT,即当前遍历的节点没有达到结尾,就会执行while循环。
在while循环里边是一个switch()控制语句,用来控制当前选中的是哪个节点,里边有三个case:
case XmlPullParser.START_DOCUMENT:满足START_DOCUMENT事件(就是xml文件的开头)
case XmlPullParser.START_TAG:满足START_TAG事件(就是xml元素节点的开头:比如本篇中的<person>)
case XmlPullParser.END_TAG::满足END_TAG事件(就是xml元素节点的结尾:比如本篇中的</person>)
在第二个case中,我们做了三个判断:
if("person".equals(pullParser.getName())):如果到达的是person元素节点,则把id赋给person
if("name".equals(pullParser.getName())):如果到达的是name元素节点,则把name赋给person
if("age".equals(pullParser.getName())):如果到达的是age元素节点,则把age赋给person
注意,在每一次switch()控制语句结束之后,会有一个event = pullParser.next(),这句话的意思是把Pull解析器指针指向下个节点。
以上,我们就把Pull解析器完成了,然后我们编写一个测试类:
注意首先配置AndroidManfiest.xml引入测试的语法,这里不多说了。
编写PersonServiceTest.java,放在cn.itcast.test文件目录下:
package cn.itcast.test;
import java.io.InputStream;
import java.util.List;
import cn.itcast.domain.Person;
import cn.itcast.service.PersonService;
import android.test.AndroidTestCase;
import android.util.Log;
public class PersonServiceTest extends AndroidTestCase{
private static final String TAG = "PersonServiceTest";
public void testPersons() throws Exception{
//通过getClassLoader()方法得到src目录下person.xml文件的输入流
InputStream xml = this.getClass().getClassLoader().getResourceAsStream("person.xml");
List<Person> persons = PersonService.getPersons(xml);
for(Person person : persons){
Log.i(TAG, person.toString());
}
}
}
然后,我们在LogCat页面中添加一个过滤器:
就可以在LogCat页面打印出来persons了。
二、采用Pull解析器生成XML内容
我们要在PersonService.java中定义一个save()方法用来生成XML文件:
/**
* 保存数据
* @param persons 数据
* @param out 输出方向
* @throws Exception
*/
public static void save(List<Person> persons, OutputStream out) throws Exception{
XmlSerializer serializer = Xml.newSerializer(); //得到实例化器
serializer.setOutput(out, "UTF-8"); //设置输出流编码格式
serializer.startDocument("UTF-8", true);//设置START_DOCUMENT,就是xml的开头
serializer.startTag(null, "persons"); //开始第一个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();
out.flush();
out.close();
}
然后,我们在测试类PersonServiceTest.java中加入一个方法:
public void testSave() throws Exception{
List<Person> persons = new ArrayList<Person>();
persons.add(new Person(43, "zhangxx",80));
persons.add(new Person(24, "lisi",80));
persons.add(new Person(12, "wangwu",80));
//放在/files目录下
File xmlFile = new File(getContext().getFilesDir(),"itcast.xml");
//打开输出流
FileOutputStream outStream = new FileOutputStream(xmlFile);
PersonService.save(persons , outStream); //调用save()方法生成xml文件
}
我们就可以在files文件目录下生成一个itcast.xml文件了