2.7 Xml格式数据的生成和解析

使用xml作为数据交互的载体是Android中非常重要的功能,比如天气预报数据、短信备份数据、通讯录数据都可以以xml的格式通过网络传输。

为了演示Xml数据的操作,我模拟了一个短信备份的案例。

需求:界面如图1-10所示。上面是三个Button,前两个分别对应两种不同方式生成xml,第三个Button点击后解析备份的xml文件,然后将数据展现在下面的ScrollView中。短信数据是模拟的假数据。


生成的xml格式如文件1-10。
【文件1-10】 xml文件格式

1.	 <?xml version="1.0" encoding="utf-8" standalone="yes" ?> 
2.	  <smses>
3.	    <sms>
4.	    <address>5554</address> 
5.	    <body>我是内容<>0</body> 
6.	    <time>1445595309201</time> 
7.	   </sms>
8.	   <sms>
9.	    <address>5555</address> 
10.	    <body>我是内容<>1</body> 
11.	    <time>1445595309201</time> 
12.	    </sms>
13.	  .............
14.	 </smses>

2.7.1 编写布局
【文件1-11】 activity_main.xml

15.	<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
16.	    xmlns:tools="http://schemas.android.com/tools"
17.	    android:layout_width="match_parent"
18.	    android:layout_height="match_parent"
19.	    android:orientation="vertical" >
20.	
21.	    <Button
22.	        android:layout_width="match_parent"
23.	        android:layout_height="wrap_content"
24.	        android:onClick="click1"
25.	        android:text="生成xml1" />
26.	
27.	    <Button
28.	        android:layout_width="match_parent"
29.	        android:layout_height="wrap_content"
30.	        android:onClick="click2"
31.	        android:text="生成xml2" />
32.	
33.	    <Button
34.	        android:layout_width="match_parent"
35.	        android:layout_height="wrap_content"
36.	        android:onClick="click3"
37.	        android:text="解析xml" />
38.	
39.	    <ScrollView
40.	        android:layout_width="match_parent"
41.	        android:layout_height="wrap_content" >
42.	
43.	        <TextView
44.	            android:id="@+id/tv_sms"
45.	            android:layout_width="match_parent"
46.	            android:layout_height="wrap_content" />
47.	    </ScrollView>
48.	
49.	</LinearLayout>

技能:

在上面布局中首次使用了ScrollView控件,其特点如下:

1、只能有一个子节点,但是子节点可以再包含多个子节点,也就是只能有一个孩子,但可以有多个孙子。

2、当包含的子控件高度超过ScrollView的高度时可以垂直滚动子控件。

1.7.2 拼接字符串方式生成Xml文件
【文件1-12】 MainActivity.java 代码片段
1. /*
2. 	 *  第一种方式生成xml
3. 	 */
4. 	public void click1(View view) throws Exception {
5. 		StringBuilder sb = new StringBuilder();
6. 		sb.append("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>");
7. 		sb.append("<smses>");
8. 		for (int i = 0; i < 50; i++) {
9. 			sb.append("<sms>");
10. 			sb.append("<address>");
11. 			sb.append(5554 + i);
12. 			sb.append("</address>");
13. 			sb.append("<body>");
14. 			sb.append("我是短信内容" + i);
15. 			sb.append("</body>");
16. 			sb.append("<time>");
17. 			sb.append(new Date().getTime());
18. 			sb.append("</time>");
19. 			sb.append("</sms>");
20. 		}
21. 		sb.append("</smses>");
22. 		/*
23. 		 * 使用系统提供的方法 获取文件输出流
24. 		 */
25. 		FileOutputStream fos = this.openFileOutput("info.xml", MODE_PRIVATE);
26. 		fos.write(sb.toString().getBytes());
27. 		fos.close();
28. 	}

技能:

上面的代码虽然也可以生成xml文件,但是无法对特殊字符进行处理,比如如果短信内容包含“</>”符号,那么xml解析器就无法完成正确的解析。因此使用的前提是你确定数据内容没有特殊字符。


1.7.3 使用XmlSerializer生成Xml文件
【文件1-13】 MainActivity.java 代码片段
1.	/*
2.		 * 第二种方式生成xml
3.		 * 使用Android提供的API
4.		 */
5.		public void click2(View view) throws Exception {
6.			//在data目录中创建info2.xml文件,获取输出流
7.			FileOutputStream fos = openFileOutput("info2.xml", MODE_PRIVATE);
8.			//通过Xml类创建一个Xml序列化器
9.			XmlSerializer serializer = Xml.newSerializer();
10.			//给序列化器设置输出流和输出流编码
11.			serializer.setOutput(fos, "utf-8");
12.			/*
13.			 * 让序列化器开发写入xml的头信息,其本质是写入内容:
14.			 * "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
15.			 */
16.			serializer.startDocument("utf-8", true);
17.			/*
18.			 * 开始写入smses标签,
19.			 * 第一个参数是该标签的命名空间, 这里不需要
20.			 */
21.			serializer.startTag(null, "smses");
22.			for (int i = 0; i < 50; i++) {
23.				//开始sms标签
24.				serializer.startTag(null, "sms");
25.				//开始address标签
26.				serializer.startTag(null, "address");
27.				//在address标签中间写入文本
28.				serializer.text("" + (5554 + i));
29.				//结束address标签
30.				serializer.endTag(null, "address");
31.				//开始body标签
32.				serializer.startTag(null, "body");
33.				//在body标签中间写入文本
34.				serializer.text("我是内容<>" + i);
35.				//结束body标签
36.				serializer.endTag(null, "body");
37.				serializer.startTag(null, "time");
38.				serializer.text(new Date().getTime()+"");
39.				serializer.endTag(null, "time");
40.				//结束sms标签
41.				serializer.endTag(null, "sms");
42.			}
43.			//结束smses标签
44.			serializer.endTag(null, "smses");
45.			//结束文档
46.			serializer.endDocument();
47.			fos.close();
48.		}

注意:

使用XmlSerializer生成xml文件是推荐的方式,因为该api内部已经实现了对特殊字符的处理。

1.7.4 使用Pull解析Xml格式数据
asserts资源目录中的文件只能读不能写,多用于随apk一起发布的固定不变的数据,比如可以将国内所有的城市列表放在里面。
这里将1.7.3节中生成的info2.xml放到asserts目录中,然后读取、解析、展现。
【文件1-14】 MainActivity.java 代码片段
1.	 //使用pull解析xml数据
2.		public void click3(View v)throws Exception{
3.			/*
4.			 * 将解析出来的数据封装在Sms中,然后保存到ArrayList中
5.			 * Sms是自定义的一个JavaBean
6.			 */
7.			ArrayList<Sms> smses = null;
8.			Sms sms = null;
9.			/*
10.			 * 调用父类提供的getAssets()方法获取AssertManager对象
11.			 */
12.			AssetManager assetManager = getAssets();
13.			//使用assetManager的open方法直接获取输入流对象
14.			InputStream inputStream = assetManager.open("info2.xml");
15.			//通过Xml的静态方法获取Xml解析器
16.			XmlPullParser parser = Xml.newPullParser();
17.			//设置输入流和编码
18.			parser.setInput(inputStream, "utf-8");
19.			//获取事件类型
20.			int event = parser.next();
21.			//如果没有解析到文档的结尾,则循环解析
22.			while(event!=XmlPullParser.END_DOCUMENT){
23.				//获取当前解析到的标签名称
24.				String tagName = parser.getName();
25.				//如果是“开始标签”事件
26.				if (event==XmlPullParser.START_TAG) {
27.					//判断当前解析到的开始标签是哪个
28.					if ("smses".equals(tagName)) {
29.						smses = new ArrayList<Sms>();
30.					}else if ("sms".equals(tagName)) {
31.						sms = new Sms();
32.					}else if ("address".equals(tagName)) {
33.						sms.setAddress(parser.nextText());
34.					}else if ("body".equals(tagName)) {
35.						sms.setBody(parser.nextText());
36.					}else if ("time".equals(tagName)) {
37.						sms.setTime(parser.nextText());
38.					}
39.					//如果是“结束标签”事件
40.				}else if (event == XmlPullParser.END_TAG) {
41.					if ("sms".equals(tagName)) {
42.						//如果是sms结尾,则将创建的sms对象添加到集合中
43.						smses.add(sms);
44.					}
45.				}
46.				//继续获取下一个事件
47.				event = parser.next();
48.			}
49.			inputStream.close();
50.			//将数据展示到界面
51.			showSms(smses);
52.			
53.		}
54.		/*
55.		 * 将短信显示到TextView中
56.		 */
57.		private void showSms(ArrayList<Sms> smses){
58.			StringBuilder sb = new StringBuilder();
59.			for(Sms s : smses){
60.				sb.append(s.toString()+"\n");
61.			}
62.			tv_sms.setText(sb.toString());
63.		}

注意:
在上面的代码中我们不仅学到如何解析xml,还学到了如何读取aserts目录中的数据。
1.7.5 Pull解析和SAX解析对比
Pull解析器的运行方式与SAX解析器相似,都属于事件驱动模式。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值。
SAX解析器的工作方式是自动将事件推入事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。






本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
这篇博客我们来介绍一下责任链模式(Chain-of-responsibility Pattern),责任联模式又称为职责链模式,是 行为型设计模式 之一。顾名思义,责任链模式中存在一个链式结构,多个节点首尾相连,每个节点都可以被拆开再连接,因此,链式结构具有很好的灵活性。将这样一种结构应用于编程领域,将每一个节点看作是一个对象,每一个对象拥有不同的处理逻辑,将一个请求从链式的首段发出,沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止,这就是责任链或者职责链的通俗定义。 转载请注明出处: h

GeekBand第十一周笔记 - 2016-07-25 17:07:19

本周的主要内容介绍Gradle,NDK,管理依赖和Git等 一、Gradle Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。 面向Java应用为主。当前其支持的语言限于Java、Groovy和Scala,计划未来将支持更多的语言。 Coding只是软件开发中的一个部分 编译源代码 运行单元测试和集成测试 执行静态代码分析,生成分析报告 创建分布版本 部署到目标环
在安卓开发中,谷歌已经为我们提供了许多原生控件,基本上能够满足我们日常的开发需求,但是某些项目中原生控件可能达不到产品所要求的各式各样的酷炫效果或功能效果,这个时候我们只能自己自定义控件来满足项目需求,我们知道自定义控件包括三种方式: 1继承控件,即继承谷歌提供的原生控件,在此基础上提供一些原生控件不具备的功能,如github上各种酷炫效果的开源组件基本上都是采用的这种方式. 2组合控件:即组合多个原生控件来达到某些单个原生控件原本不具备的功能,这个在日常开发中应该是使用的比较多的,如基本上每个App都存

Android多点触摸交互处理 - 2016-07-25 17:07:15

安卓手机中,多点触摸是是最基本的操作,下面就使用程序进行演示多点触摸操作 一、获取触摸事件中的点击,移动和抬起事件,创建新的安卓项目,如下面代码所示,分别为MainActivity类代码和Layout布局文件,用于实现获取点击事件 1.1、MainActivity类中代码,代码中为布局对象root添加监听事件,使用switch进行对屏幕时间进行判断,用于判断事件的按下还是移动,在代码中      root=(RelativeLayout) findViewById(R.id.content);用于绑定布局
内容是博主照着书敲出来的,博主码字挺辛苦的,转载请注明出处,后序内容陆续会码出。 前言:ListView——列表,它作为一个非常重要的显示方式,不管是在Web中还是移动平台中,都是一个非常好的、不开或缺的展示信息的工具。在Android中,ListView控件接管了这一重担,在大量的场合下,我们都需要使用这个控件。虽然在Android 5.X时代,RecyclerView在很多地方都在逐渐取代ListView,但ListView的使用范围依然非常的广泛,它这万年老大哥的地位也不是轻易就能撼动的。下面就介绍
Android ListView使用简介 ListView 是 Android 软件开发中十分常用也十分重要的一个 UI 控件。 ListView 的每一个子项可以是一个简单的字符串,也可以是一组 View 的组合,开发者完全可以根据自己的需求来定义显示的形式。 如何使用一个 ListView 实现对数据的显示呢 ? 1. 创建 ListView 控件,已备数据显示 2. 准备要显示的数据 3. 为 ListView 构建一个数据适配器 (Adapter) 4. 绑定适配器 5. 处理 ListView
转载请标明出处: 一片枫叶的专栏 文本我们将讲解android studio打包apk,aar,jar包的相关知识。apk包就是android系统的安装包,这里没什么好说的,aar包是android中独有的类库包,而jar包是java中特有的类库包,在具体的介绍打包之前,我们先来aar包和jar包的区别。 jar包与aar包的区别 jar是java字节码文件(class文件)的归档文件,其不包含android中的资源文件等信息; aar是android中特有的归档文件,既包含字节码文件也包含android
欢迎转载,转载请注明出处: http://blog.csdn.net/dmk877/article/details/51980734 在上一篇文章中,我们详细讨论了Tween动画的xml的实现以及interpolator的使用,相信通过上篇文章大家对Tween动画的xml属性的配置会有一个详细的理解,当然这篇文章也是承接上篇文章,所以强烈建议先阅读上篇文章: Android开发之Tween(补间动画)完全解析(上) ,这篇文章将从代码的角度实现上篇文章的效果。 如有疑问请留言,如有谬误欢迎批评指正。 Tw

Android闹钟设置的解决方案 - 2016-07-25 14:07:00

Android设置闹钟并不像IOS那样这么简单,做过Android设置闹钟的开发者都知道里面的坑有多深。下面记录一下,我解决Android闹钟设置的解决方案。 主要问题 API19开始AlarmManager的机制修改。 应用程序被Kill掉后,设置的闹钟不响。 6.0以上进入Doze模式会使JobScheduler停止工作。 手机设置重启后,闹钟失效问题。 API19以上AlarmManager机制的修改 API19之前AlarmManager提供了三个设置闹钟的方法,由于业务需求闹钟只需要一次性,所以
start_kernel之前的汇编代码建立了内核临时页表,完成了内核区域的静态线性映射,保证内核可以在舒适的虚拟地址空间(运行地址和链接地址一致)运行。进入start_kernel之后就要准备建立完整的页表映射,这部分工作是在paging_init中完成。 不过在建立完整页表映射之前还需要进行一些准备工作,本文来分析下。 为了简化整个代码流程,便于分析,我的设备内核配置为不使用高端内存,不配置CONFIG_HIGHMEM。bootargs中传给内核的mem=256. 内核版本号:3.4.55 paging