对xml的解析,我们在将j2ee中,常使用的解析器是DOM和SAX。而在android中,我们还可以使用PULL解析器。
pull是android中内置的解析器,可以直接的使用相关的类来解析大部分的xml文件了。pull也是采用事件驱动模型,跟SAX解析XML文件差不多。
xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<people>
<person id="001">
<name>XY1</name>
<age>22</age>
</person>
<person id="002">
<name>XY2</name>
<age>22</age>
</person>
</people>
这个xml文件为了获取流的方便,我是放在src目录下的。
解析的具体方法:
public class XmlTest extends Activity {
private InputStream in = null;
private List<Person> list = null;
private Person person = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 将xml文件转换为输入流
in = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("people.xml");
// 新建List集合,来存放person数据
try {
// 获取解析实例
XmlPullParser xmlparser = XmlPullParserFactory.newInstance()
.newPullParser();
// 设置解析的xml
xmlparser.setInput(in, "UTF-8");
// 取得事件
int event = xmlparser.getEventType();
/*
* 开始循环解析xml里面的元素 当没到文档结束的位置,就一直循环下去
*/
while (event != XmlPullParser.END_DOCUMENT) {
// 获取节点的名字
String Node = xmlparser.getName();
if (Node != null) {
Log.i("Node", Node);
} else {
Log.i("Node", Node + "=null");
}
switch (event) {
// 文档开始,即:<?xml version="1.0" encoding="UTF-8"?>
case XmlPullParser.START_DOCUMENT:
// 数据初始化
list = new ArrayList<Person>();
break;
// 节点
case XmlPullParser.START_TAG:
//初始化对象。
if ("person".equals(Node)) {
person = new Person();
person.setId(Integer.parseInt(xmlparser
.getAttributeValue(0)));
}
//设置对象的姓名
else if ("name".equals(Node)) {
person.setName(xmlparser.nextText());
}
//设置对象的年龄
else if ("age".equals(Node)) {
person.setAge(xmlparser.nextText());
}
break;
// 结束节点
case XmlPullParser.END_TAG:
if ("person".equals(Node)) {
list.add(person);
person = null;
}
break;
default:
break;
}
// 继续下一个标签
event = xmlparser.next();
}
Log.i("list", list.get(0).toString() + "**"
+ list.get(1).toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
在上面的实例中,大家可以看到我在获取节点的时候,是打印了节点名字的,判断当节点获取为空的时候也会打印出来“Node=null”的字符窜。
我们来看下打印的日志:
在最后的时候,打印的list集合是符合我们的原来xml数据。
但为啥每次节点都会多个空节点呢??
原来,在xml中标签和内容都可以叫做节点。而节点分为两类,一个是ElementNode(元素节点),一个是TextNode(文本节点)。而在我们的xml中,每个节点都是换了行的,虽然看起来什么也没有,但也是节点,是文本节点,里面有回车和空格。
也许我这样更能理解点,可以明显的看出每个节点之间是换行了的。
那么该如何去纠正了??
1.修改xml的格式:
可以看到效果:
在这,name和age就没有空节点了。
不过这样的方式,只能说是一种取巧了,因为你不可能把所有的xml都放在同一行吧。
我们如此在意这个空节点的原因是,每次运行到空节点的时候,都会循环遍历依次,消耗我们的资源。如果当遇到空节点的时候,不遍历是不是可以呢?
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 将xml文件转换为输入流
in = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("people.xml");
// 新建List集合,来存放person数据
try {
// 获取解析实例
XmlPullParser xmlparser = XmlPullParserFactory.newInstance()
.newPullParser();
// 设置解析的xml
xmlparser.setInput(in, "UTF-8");
// 取得事件
int event = xmlparser.getEventType();
// 初始化person对象
person = new Person();
// 初始化集合
list = new ArrayList<Person>();
/*
* 开始循环解析xml里面的元素 当没到文档结束的位置,就一直循环下去
*/
while (event != XmlPullParser.END_DOCUMENT) {
// 获取节点的名字
String Node = xmlparser.getName();
if (Node != null) {
// Log.i("Node", Node);
} else {
// Log.i("Node", Node + "=null");
event = xmlparser.next();
Node = xmlparser.getName();
}
switch (event) {
// 文档开始,即:<?xml version="1.0" encoding="UTF-8"?>
case XmlPullParser.START_DOCUMENT:
break;
// 节点
case XmlPullParser.START_TAG:
if ("person".equals(Node)) {
// person=new Person();
person.setId(Integer.parseInt(xmlparser
.getAttributeValue(0)));
}
// 设置对象的姓名
else if ("name".equals(Node)) {
person.setName(xmlparser.nextText());
}
// 设置对象的年龄
else if ("age".equals(Node)) {
person.setAge(xmlparser.nextText());
}
break;
// 结束节点
case XmlPullParser.END_TAG:
if ("person".equals(Node)) {
list.add(person);
person = new Person();
}
break;
default:
break;
}
if (Node != null) {
Log.i("Node", Node);
} else {
Log.i("Node", Node + "=null");
}
// 继续下一个标签
event = xmlparser.next();
}
Log.i("list", list.get(0).toString() + "," + list.get(1).toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
更改了初始化集合和对象的地方,在获取到null节点的时候,加了判断的语句。
这就是效果图了,没有运行到null的节点了吧。
至于为啥,输出的集合元素中的有换行,那是因为解析的xml的字符窜中带有换行的字符。