1.Pull解析器概述
Pull解析和Sax解析很相似,都是轻量级的解析xml工具,在Android的内核中已经嵌入了Pull工具包,所以我们不需要再添加第三方jar包。Pull解析xml文件过程中会触发相应的事件,默认解析完一个标签则不继续往下解析,只有调用next方法,才继续往下解析,根据解析器的getEventType来获得解析对象的类型。
2.Pull解析数据
/*
* MainActivity.java
*/
package com.baidu.parsexmltest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.os.Bundle;
import android.app.ListActivity;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
public class MainActivity extends ListActivity {
private ListView listView;
private List<Person> persons;
private List<Map<String, String>> list;
private Map<String, String> map;
private InputStream is;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = this.getListView(); //得到ListView控件,由于继承了ListActivity可以直接得到
list = new ArrayList<Map<String,String>>();
read(); //读取xml文件
listView.setAdapter(new SimpleAdapter(this, list, R.layout.item,
new String[]{"id", "name", "age"},
new int[]{R.id.id, R.id.name, R.id.age}));
save(); //保存xml文件
}
/**
* 保存xml文件
*/
public void save() {
File file = new File(this.getApplication().getFilesDir(),
"personNew.xml"); //定义file对象,路径为/data/dara/<package name>/files/personNew.xml
try {
FileOutputStream fos = new FileOutputStream(file);
XmlTool.save(persons, fos); //主要保存xml方法
Toast.makeText(this, R.string.success, Toast.LENGTH_SHORT).show();//保存成功提示
return ;
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(this, R.string.fail, Toast.LENGTH_SHORT).show(); //保存失败提示
}
/*
* 读取xml文件
*/
public void read() {
try {
is = this.getAssets().open("persons.xml"); //打开assets目录中保存的xml文件
persons = new XmlTool().parser(is); //主要读取xml文件方法
for (Person p : persons) {
map = new HashMap<String, String>();
map.put("id", Integer.toString(p.getId()));
map.put("name", p.getName());
map.put("age", Integer.toString(p.getAge()));
list.add(map);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* XmlTool.java
* 解析xml文件盒保存xml主要工具
*/
package com.baidu.parsexmltest;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import android.util.Xml;
public class XmlTool {
private List<Person> persons;
Person person = null;
/**
* 解析xml文件
* @param in 字节输入流
* @return 返回list集合
* @throws Exception
*/
public List<Person> parser(InputStream in) throws Exception {
/*
* XmlPullParser解析xml文件,读完相应的标签后会触发相应的事件!
* 对一个xml文件读取存在5种类型
* <?xml version="1.0" encoding="utf-8"?> //StartDocument
* <person> //StartTag
* info //Text
* </person> //EndTag
* //EndDocument
* 默认读完一个标签后,不再继续往下读取,只有执行解析器的next方法,才会继续往下执行解析操作
*/
// 1.定义解析器
XmlPullParser parser = Xml.newPullParser();
// 2.设定解析器读取的字节流对象,含有编码方式
parser.setInput(in, "UTF-8");
// 3.得到解析返回的事件类型
int type = parser.getEventType();
// 4.根据事件类型,进行选择操作
while(type != XmlPullParser.END_DOCUMENT){
switch (type) {
case XmlPullParser.START_DOCUMENT: //主要完成初始化动作
persons = new ArrayList<Person>();
break;
case XmlPullParser.START_TAG: //开始标签,完成数据操作
if("person".equals(parser.getName())){
person = new Person();
person.setId(Integer.parseInt(parser.getAttributeValue(0)));
} else if("name".equals(parser.getName())){
person.setName(parser.nextText()); //可以直接获得文本标签信息
} else if("age".equals(parser.getName())){
person.setAge(Integer.parseInt(parser.nextText()));
}
break;
case XmlPullParser.END_TAG: //结束标签
if("person".equals(parser.getName())){
persons.add(person);
}
break;
}
type = parser.next(); //下一个标签,默认读完该标签不再继续往下执行读取操作
}
return persons;
}
/**
* 保存xml文件
* @param list list集合对象
* @param fos 输出流对象
* @throws Exception
*/
public static void save(List<Person> list, FileOutputStream fos) throws Exception{
// 1.定义Xml序列器
XmlSerializer serializer = Xml.newSerializer();
// 2.为该序列器对象设定输出流
serializer.setOutput(fos, "UTF-8");
// 3.xml写入信息
serializer.startDocument("UTF-8", true); //能否单独存在
serializer.startTag(null, "persons"); //第一个参数为命名空间
for(Person person:list){
serializer.startTag(null, "person");
serializer.attribute(null, "id", Integer.toString(person.getId()));//赋予属性信息
serializer.startTag(null, "name");
serializer.text(person.getName());
serializer.endTag(null, "name");
serializer.startTag(null, "age");
serializer.text(Integer.toString(person.getAge()));
serializer.endTag(null, "age");
serializer.endTag(null, "person");
}
serializer.endTag(null, "persons");
serializer.endDocument(); //文档结束
fos.flush();
fos.close();
return;
}
}
/*
* Person.java
*/
package com.baidu.parsexmltest;
public class Person {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- ListView布局 item.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40sp"
android:orientation="horizontal" >
<TextView android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:textSize="16sp"
android:id="@+id/id"/>
<TextView android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:layout_weight="1"
android:textSize="16sp"
android:id="@+id/name"/>
<TextView android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:layout_weight="1"
android:textSize="16sp"
android:id="@+id/age"/>
</LinearLayout>
3.更新xml文件
如果只是简单的生成xml文件,则可以使用pull方式的Xml.newSerializer()去生成一个xml文档很方便,但是对其修改很麻烦。如果只为修改xml文件,可以参考dom解析方式,添加或者移除一个节点。