在我们做有关android项目的时候,肯定会涉及到对xml文件的解析操作。以下给大家介绍一下xml文件的解析。包括DOM、SAX、Pull以及曾经我们用到的DOM4J和JDOM:

要解析的XML文件:person.xml

<?

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

>
<persons>
<person id="001">
<name>zhangsan</name>
<age>25</age>
</person>
<person id="002">
<name>lisi</name>
<age>23</age>
</person>
</persons>

创建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;
}
@Override
public String toString() {
return "Person [age=" + age + ", id=" + id + ", name=" + name + "]";
} }

1、DOM解析XML:DOM解析是将XML文件所有加载,组装成一颗dom树,然后通过节点以及节点之间的关系来解析xml文件

public static List<Person> getPersons(InputStream inStream) throws Throwable{
List<Person> persons = new ArrayList<Person>();
//创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//创建文档树模型,全部的Node都以一定的顺序包括在Document对象之内,
//排列成一个树状结构,以后对XML文档的全部操作都与解析器无关
Document documnet = builder.parse(inStream);
//获取根元素
Element root = documnet.getDocumentElement();
//获得根元素下的person节点列表
NodeList personNodes = root.getElementsByTagName("person");
for(int i=0 ; i < personNodes.getLength(); i++){
Person person = new Person();
//获得节点中的元素
Element personElement = (Element)personNodes.item(i);
//获得person中id属性
person.setId(new Integer(personElement.getAttribute("id")));
//获得person节点下的子节点
NodeList personChilds = personElement.getChildNodes();
for(int y=0 ; y < personChilds.getLength(); y++){
if(personChilds.item(y).getNodeType()==Node.ELEMENT_NODE){//推断当前节点是否是元素类型节点
Element childElement = (Element)personChilds.item(y);
if("name".equals(childElement.getNodeName())){
//获得对应元素的值
person.setName(childElement.getFirstChild().getNodeValue());
}else if("age".equals(childElement.getNodeName())){
person.setAge(new Short(childElement.getFirstChild().getNodeValue()));
}
}
}
persons.add(person);
}
return persons;
}

2、SAX解析XML:顺序读取XML文件,不须要一次所有装载整个文件,因为移动设备的内存资源有限。SAX的顺序读取方式更适合移动开发

public List<Person> getPersons(InputStream inStream) throws Throwable{
//创建SAXParserFactory
SAXParserFactory factory = SAXParserFactory.newInstance();
//创建SAX解析器
SAXParser parser = factory.newSAXParser();
//创建XML解析处理器
PersonParser personParser = new PersonParser();
//将XML解析处理器分配给解析器,对文档进行解析,将每一个事件发送给处理器
parser.parse(inStream, personParser);
inStream.close();
return personParser.getPersons();
} //定义解析处理器
private final class PersonParser extends DefaultHandler{
private List<Person> persons = null;//将解析的数据放在List集合中
private String tag = null;//定义一个全局变量的标签名称
private Person person = null; public List<Person> getPersons() {
return persons;
} //解析Document
@Override
public void startDocument() throws SAXException {
//解析<persons>部分
persons = new ArrayList<Person>();
} @Override
public void endDocument() throws SAXException {
System.out.println("end parse xml");
} /**
* 解析Element
* namespaceURI 命名空间
* localName 不带前缀部分<person id="001">--->person
* qName 带前缀部分<abc:person id="001">---->abc:worker
* attributes 属性集合 <abc:person id="001">---->id="001"....
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//解析<person id="001">部分
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 {
//解析当中的文本<name>zhangsan</name>-->zhangsan
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));
}
}
} //解析结束元素
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("person".equals(localName)){
persons.add(person);
person = null;
}
tag = null;
}
}

3、pull解析XML:pull解析和SAX解析非常相似。都是轻量级的解析,在android内核中已经嵌入了pull。所以我们不须要再加入第三方jar包来支持pull

/**
* 使用pull解析XML文档
* @param inStream
* @return
* @throws Throwable
*/
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>();//初始化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;
}

採用pull解析器创建一个xml文档:

	/**
* 使用pull解析器创建一个xml文档
* @param persons
* @param writer
* @throws Throwable
*/
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();
}

在android项目中通过Junit对各方法进行測试:

注意在使用junit的时候,须要在AndroidMainifest.xml中增加:

<uses-library android:name="android.test.runner" />
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.xin.activity" android:label="Tests for My App" />

编写我们的java測试类:

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("person.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("person.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("person.xml");
List<Person> persons = PULLPersonService.getPersons(inStream);
for(Person person : persons){
Log.i(TAG, person.toString());
}
}
}

执行输出就可以得到我们想要的结果!

几种方法比較:

SAX:一行一行读取。效率高,读取到对应须要的数据后不再往下操作,操作复杂,适合移动设备

 DOM:操作简单,一開始载入一个DOM树,当XML文件相对照计较大的时候影响效率,速度慢

* Pull解析和Sax解析不一样的地方有

 * (1)pull读取xml文件后触发对应的事件调用方法返回的是数字

 * (2)pull能够在程序中控制想解析到哪里就能够停止解析

事实上pull解析xml不仅适用于android,在我们的javase中也能够使用pull解析器来解析xml文件,只是须要导入对应的jar包:

kxml2-2.3.0.jar,下载地址:http://kxml.sourceforge.net/

xmlpull_1_1_3_4c.jar  下载地址:http://www.xmlpull.org/

曾经我们还使用了DOM4J和JDOM来解析xml。能够參见我的博客,只是须要导入对应的支持jar包:

DOM4J解析XML:http://blog.csdn.net/harderxin/article/details/7285770

JDOM解析XML:http://blog.csdn.net/harderxin/article/details/7285754

Android之旅十四 android中的xml文件解析的更多相关文章

  1. Android之旅十六 android中各种资源的使用

    android中各种资源的使用: 在android开发中,各种资源的合理使用应该在各自的xml中进行定义,以便反复使用; 字符串资源:strings.xml,xml中引用:@string/XXX,ja ...

  2. Android笔记(六十四) android中的动画——补间动画(tweened animation)

    补间动画就是只需要定义动画开始和结束的位置,动画中间的变化由系统去补齐. 补间动画由一下四种方式: 1.AplhaAnimation——透明度动画效果 2.ScaleAnimation ——缩放动画效 ...

  3. Android笔记二十四.Android基于回调的事件处理机制

        假设说事件监听机制是一种托付式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源和事件监听器是统一的,或者说事件监听器全然消失了,当用户在GUI控件上激发某个事件时,控 ...

  4. Android进阶(二十四)Android UI---界面开发推荐颜色

    Android UI---界面开发推荐颜色   在Android开发过程中,总要给app添加一些背景,个人认为使用纯色调便可以达到优雅的视觉效果. 补充一些常用的颜色值:colors.xml < ...

  5. tomcat中server.xml文件解析

    下面我们将讲述这个文件中的基本配置信息,更具体的配置信息见tomcat的文档 元素名 属性 解释 server port 指定一个端口,这个端口负责监听关闭tomcat的请求 shutdown 指定向 ...

  6. android XMl 解析神奇xstream 五: 把复杂对象转换成 xml ,并写入SD卡中的xml文件

    前言:对xstream不理解的请看: android XMl 解析神奇xstream 一: 解析android项目中 asset 文件夹 下的 aa.xml 文件 android XMl 解析神奇xs ...

  7. Android开发 ---如何操作资源目录中的资源文件2

    Android开发 ---如何操作资源目录中的资源文件2 一.颜色资源管理 效果图: 描述: 1.改变字体的背景颜色 2.改变字体颜色 3.改变按钮颜色 4.图像颜色切换 操作描述: 点击(1)中的颜 ...

  8. 修改Android中strings.xml文件, 动态改变数据

    有些朋友可能会动态的修改Android中strings.xml文件中的值,在这里给大家推荐一种简单的方法.strings.xml中节点是支持占位符的,如下所示: <string name=&qu ...

  9. Android开发---如何操作资源目录中的资源文件4 ---访问xml的配置资源文件的内容

    Android开发---如何操作资源目录中的资源文件4 XML,位于res/xml/,这些静态的XML文件用于保存程序的数据和结构. XmlPullParser可以用于解释xml文件 效果图: 描述: ...

随机推荐

  1. LightOJ 1414 February 29(闰年统计+容斥原理)

    题目链接:https://vjudge.net/contest/28079#problem/R 题目大意:给你分别给你两个日期(第二个日期大于等于第一个日期),闰年的2月29日称为闰日,让你求两个日期 ...

  2. java1.8环境配置+win10系统

    Java环境配置相关 Java jdk 1.8版本的环境配置和1.7版本 存在一些差异,当然不同的操作系统可能会对jdk配置有一定的变化.本文我主要说1.8版本的jdk在window10 系统上的配置 ...

  3. laravel5.1--数据库操作

    1 配置信息 1.1配置目录: config/database.php 1.2配置多个数据库 //默认的数据库 'mysql' => [ 'driver' => 'mysql', 'hos ...

  4. hdu 5877(树状数组+dfs)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  5. 洛谷P2097 资料分发1 题解

    题目传送门 这道题竟然是橙色的: 因为可以用并查集来做,当然您用dfs也可以,不过应该要加优化. 一开始就把读入的合并起来,最后逐个查找就好啦... #include<bits/stdc++.h ...

  6. CyclicBarrier 简介

    CyclicBarrier 简介 CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier). 它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最 ...

  7. 使用自己的域名解析 cnblogs 博客

    使用自己的域名解析 cnblogs 博客(博客园) 1.实现原理 用户访问 -> 阿里云解析 -> github page 跳转 -> 真实的博客地址 2.创建 github pag ...

  8. REST API 支持方式

    1.JSONPlaceholder 是一个提供免费的在线 REST API 的网站,我们在开发时可以使用它提供的 url 地址测试下网络请求以及请求参数.或者当我们程序需要获取一些假数据.假图片时也可 ...

  9. 洛谷P3834 [模板]可持久化线段树1(主席树) [主席树]

    题目传送门 可持久化线段树1(主席树) 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定 ...

  10. 【小思考】Python里面有声明和定义分离这一说么?

    第一部分: 探究这个问题,还是因为编程的时候碰到了这个错误: 提示tcplink没有定义,tcplink是我自己写的一个给监听到的tcp连接请求分配新线程的函数,不过是写在了下面,就像这样: 如果是C ...