Android之旅十四 android中的xml文件解析

在我们做有关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

时间: 2024-10-25 20:23:23

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

Android之旅十五 android中的网络操作

android中的网络操作和java里面没有什么区别,java里面的很多网络操作方法都可以搬到android中去使用,主要几个点: 1.post和get请求的区别,大家可以在网上查阅有关资料进行了解,get主要以向地址中拼接字符串参数发送到服务器,长度有限制,并且请求参数暴露在地址栏中,不怎么安全:post则主要是将请求参数转换为相应的http协议请求体发送到服务器,相比get方式,参数的长度没有限制,并且参数信息不会暴露给用户: 2.我们在java web里面通过浏览器以post方式发送数据,

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

android中各种资源的使用: 在android开发中,各种资源的合理使用应该在各自的xml中进行定义,以便重复使用; 字符串资源:strings.xml,xml中引用:@string/XXX,java代码中引用:R.string.XXX 样式资源:styles.xml,xml中引用:@style/XXX,java代码中引用:R.style.XXX 图片资源:colors.xml,xml中引用:@color/XXX,java代码中引用:R.color.XXX 尺寸资源:dimens.xml,x

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

补间动画就是只需要定义动画开始和结束的位置,动画中间的变化由系统去补齐. 补间动画由一下四种方式: 1.AplhaAnimation——透明度动画效果 2.ScaleAnimation ——缩放动画效果 3.TranslateAnimation——位移动画效果 4.RotateAnimation——旋转动画效果 1.AplhaAnimation AplhaAnimation的参数: fromAlpha:动画开始时的透明度,0.0表示完全透明 toAlpha:动画结束时的透明度,1.0表示完全不透

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

如果说事件监听机制是一种委托式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源和事件监听器是统一的,或者说事件监听器完全消失了,当用户在GUI控件上激发某个事件时,控件自己特定的方法将会负责处理该事件. 转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空) 一.View类的常见回调方法 为了使用回调机制来处理GUI控件上所发生的事件,需要为该组件提供对应的事件处理方法,而Java又是一种静态语言,我们无法为每个对象动态地添

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

Android UI---界面开发推荐颜色   在Android开发过程中,总要给app添加一些背景,个人认为使用纯色调便可以达到优雅的视觉效果. 补充一些常用的颜色值:colors.xml <?xml version="1.0" encoding="utf-8" ?> <resources> <color name="white">#ffffff</color><!--白色 --> &

tomcat中server.xml文件解析

下面我们将讲述这个文件中的基本配置信息,更具体的配置信息见tomcat的文档 元素名 属性 解释 server port 指定一个端口,这个端口负责监听关闭tomcat的请求 shutdown 指定向端口发送的命令字符串 service name 指定service的名字 Connector (表示客户端和service之间的连接) port 指定服务器端要创建的端口号,并在这个断口监听来自客户端的请求 minProcessors 服务器启动时创建的处理请求的线程数 maxProcessors

Android基础之十四数据存储 之 SQLite数据库详解

Android基础之十四数据存储 之 SQLite数据库详解 SQLite 是一款 轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 K 的内存就足够了,因而特别适合在移动设备上使用. SQLite 不仅支持标准的 SQL 语法,还遵循了数据库的 ACID( 原子性(Atomicity) .一致性(Consistency) . 隔离性(Isolation) . 持久性(Durability))事务,所以只要你以前使用过其他的关系型数据库,就可以很快地上手 SQLite.而

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

前言:对xstream不理解的请看: android XMl 解析神奇xstream 一: 解析android项目中 asset 文件夹 下的 aa.xml 文件 android XMl 解析神奇xstream 二: 把对象转换成xml android XMl 解析神奇xstream 三: 把复杂对象转换成 xml android XMl 解析神奇xstream 四: 将复杂的xml文件解析为对象 1.建立JavaBeen package com.android10; public class

解决Android中fragment_main.xml文件中的组件获取的问题

package com.dhy.phonedial; import android.app.Activity; import android.app.Fragment; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.Me