Android开发之使用DefaultHandler处理XML数据
2013-11-11 11:11
381 查看
一、定义规则
XML数据结构定义
请记住上面的定义,后面我会用“标签开始”、“文本”、“标签结束”表示SAX正在处理哪部分XML数据
事件模型
为什么这里我要谈到这个,因为SAX处理XML数据是采用事件的形式来处理,下面我们来简单的做个介绍。当我们处理XML数据中遇到一个开始标签后SAX会告诉你“我遇到了一个开始标签,这个标签是XXXX”,等你作出反应后,它会继续往下
这时它遇到了一段文本,SAX告诉你“我遇到了一段文本,是XXXX”,然后继续等你作出反应,接着下去就遇到了结束标签,SAX仍然会
告诉你“我到了一个结束标签是XXX”。SAX就是以这样的方式将整个XML数据全部处理完。
二、为何使用
节约内存
这里我要声明我的目标设备是手机,而不是电脑等等。而手机的内存是很小的,同时也十分珍贵。或许你会说现在手机都是1GB、2GB内存,根本不用着想。但是我们既然开发应用,当然是希望使用的人越多越好,而大多数手机设备是没有那么多内存的,所以我们
需要尽量使我们开发的应用能够适合于很多的设备。
效率高
手机不仅仅有着内存少的缺点,而且本身的CPU处理能力也是相对较慢的。所以我们要让代码的速度更快更快,否则用户就会感觉使用你的应用总是卡顿半天,从而会选择其他更优秀的应用。而SAX在执行效率方面也是很客观的,当然这个前提是你的代码够简洁,而
不是把所有逻辑处理任务都放进处理XML数据的方法里面。
三、安卓如何使用
DefaultHandler类
这是安卓中内置的用于SAX处理XML的类,但是大多情况下我们都需要继承该类重写部分方法,才能达到处理XML数据的功能。startDocument方法
这是第一个需要重写的方法,每处理一个XML文档都会响应一次。所以这个方法里可以写需要初始化的代码。startElement方法
这是处理每个节点所触发的方法,通过这个方法你可以直接当前处理的节点的名称以及属性。characters方法
当处理一个节点之间的文本时候触发该方法,但是该方法并不会告诉你当前文本的所属标签,而仅仅是告诉你文本内容。endElement方法
遇到一个节点的结束标签时,将会出发这个方法,并且会传递结束标签的名称。endDocument方法
如果当前的XML文档处理完毕后,将会触发该方法,在此方法内你可以将最终的结果保存并且销毁不需要使用的变量。四、执行流程举例
下面我将以下的XML文件为例,说明SAX具体如何处理XML文件。(部分文本因为是中文所以经过了URL编码)
<notic> <id>1</id> <title>%3cs%3edsds%3c%2fs%3e</title> 4 <content>%e5%86%85%e5%ae%b91</content> <author>1</author> </notic>
2. 下面是具体的响应过程
方法名称 | localName(标签名称) | ch[](文本名称) |
startDocument | -- | -- |
startElement | notic | -- |
startElement | id | -- |
characters | -- | 1 |
endElement | id | -- |
startElement | title | -- |
characters | -- | %3cs%3edsds%2c%2fs%3e |
endElement | title | -- |
startElement | content | -- |
characters | -- | %e5%86%85%e5%ae%b91 |
endElement | content | -- |
startElement | author | -- |
characters | -- | 1 |
endElement | author | -- |
endElement | notic | -- |
endDocument | -- | -- |
3.通过上面的分析我们可以清楚的看到,它是如何处理XML文档的,下面是列举的一个顺序图:
<!-- startDocument --> <notic> -> startElement(localName = 'notic') <id> -> startElement(localName = 'id') 1 -> characters(ch[] = '1') </id> -> endElement(localName = 'id') <title> -> startElement(localName = 'title') %3c... -> characters(ch[] = '略') </title> -> endElement(localName = 'title') <content> -> startElement(localName = 'content') %e5... -> characters(ch[] = '略') </content> -> endElement(localName = 'content') <author> -> startElement(localName = 'author') 1 -> characters(ch[] = '1') </author> -> endElement(localName = 'author') </notic> -> endElement(localName = 'notic') <!-- endDocument -->
五、实例
下面我们采用一个实例来学习如何使用SAX解析XML下面是我们需要解析的XML文档
<result> <notic> <id>1</id> <title>%3cs%3edsds%3c%2fs%3e</title> <content>%e5%86%85%e5%ae%b91</content> <author>1</author> <time>2013-11-01 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>False</warn> </notic> <notic> <id>2</id> <title>%e6%b5%8b%e8%af%952</title> <content>%e5%86%85%e5%ae%b92</content> <author>2</author> <time>2013-11-02 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>True</warn> </notic> <notic> <id>3</id> <title>%e6%b5%8b%e8%af%953</title> <content>%e5%86%85%e5%ae%b93</content> <author>3</author> <time>2013-11-03 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>False</warn> </notic> <notic> <id>4</id> <title>%e6%b5%8b%e8%af%954</title> <content>%e5%86%85%e5%ae%b94</content> <author>4</author> <time>2013-11-04 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>False</warn> </notic> <notic> <id>5</id> <title>%e6%b5%8b%e8%af%955</title> <content>%e5%86%85%e5%ae%b95</content> <author>5</author> <time>2013-11-05 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>False</warn> </notic> <notic> <id>6</id> <title>%e6%b5%8b%e8%af%956</title> <content>%e5%86%85%e5%ae%b96</content> <author>6</author> <time>2013-11-06 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>True</warn> </notic> <notic> <id>7</id> <title>%e6%b5%8b%e8%af%956</title> <content>%e5%86%85%e5%ae%b96</content> <author>6</author> <time>2013-11-06 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>True</warn> </notic> <notic> <id>8</id> <title>%e6%b5%8b%e8%af%956</title> <content>%e5%86%85%e5%ae%b96</content> <author>6</author> <time>2013-11-06 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>True</warn> </notic> <notic> <id>9</id> <title>%e6%b5%8b%e8%af%956</title> <content>%e5%86%85%e5%ae%b96</content> <author>6</author> <time>2013-11-06 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>True</warn> </notic> <notic> <id>10</id> <title>%e6%b5%8b%e8%af%956</title> <content>%e5%86%85%e5%ae%b96</content> <author>6</author> <time>2013-11-06 12-00-00</time> <section>%e4%bf%a1%e6%81%af%e5%a4%84</section> <warn>True</warn> </notic> </result>
开始继承DefaultHandler类
public class SAXForHandler extends DefaultHandler { //用于保存当前处理的节点名称 private String preTag; //用于保存当前处理的节点数据 private Map<String,String> curMap; //用于保存最终的结果 private ArrayList<Map<String,String>> result; //重写startDocument public void startDocument() { //初始化 result = new ArrayList<Map<String,String>>(); } public void startElement(String uri,String localName,String qName,Attributes attributes) { //判断当前节点是notic时表示是一项数据,创建一个新的项 if("notic".equals(localName)) { curMap = new HashMap<String,String>(); } //用于保存当前处理的节点名称,用于后面判断用 preTag = localName; } public void characters(char[] ch,int start,int length) { //从char[]数据转换成String String data = new String(ch,start,length); if("id".equals(preTag)) { //表示当前的文本值是id标签的 curMap.put("id",data); }else if("title".equals(preTag)) { //表示当前的文本值是title标签的 curMap.put("title",data); }else if("content".equals(preTag)) { //表示当前的文本值是content标签的 curMap.put("content",data); } else if("time".equals(preTag)) { //表示当前的文本值是time标签的 curMap.put("time",data); }else if("section".equals(preTag)) { //表示当前的文本值是section标签的 curMap.put("section",data); }else if("warn",equals(preTag)) { //表示当前的文本值是warn标签的 curMap.put("warn",data); } } public void endElement(String uri,String localName,String qName) { if("notic".equals(localName)) { //表示一条数据处理完毕 result.add(curMap); curMap = null; } //每次处理完一个节点都要将preTag重置 preTag = null; } public void endDocument() { //XML处理结束,因为没有使用到必须释放的资源所以这里为空 } }
如何使用该SAXForHandler
//in为InputStream表示读取的XML文件流 SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); SAXForHandler sfh = new SAXForHandler(); sp.parser(in,sfh); //如果要想获得处理后的结果 //可以公开一个方法,用来将result通过return的方法传递给调用者.
六、以下是本人开发的一个工具类,可以方便的通过代码调整SAXForHandler来处理不同的XML
package com.ninesoft.newprower.xml; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class SaxForXmlHandler extends DefaultHandler { private String[] _needTag; private ArrayList<Map<String,String>> _notics; private Map<String,String> current; private String preTag; private String _nodeTag; //构造函数 public SaxForXmlHandler(String tag) { this._nodeTag = tag; } public SaxForXmlHandler(String[] need) { this._needTag = need; } public SaxForXmlHandler(String tag,String[] need) { this._nodeTag = tag; this._needTag = need; } //获取设置每个节点数据的标签名称 public void setNodeTag(String tag) { this._nodeTag = tag; } public String getNodeTag() { return this._nodeTag; } //获取设置包含数据的标签名称数组 public void setNeedTag(String[] need) { this._needTag = need; } public String[] getNeedTag() { return this._needTag; } //获得最终处理后的数据 public ArrayList<Map<String,String>> getResult() { return this._notics; } //文档开始 @Override public void startDocument() throws SAXException { this._notics = new ArrayList<Map<String,String>>(); this.preTag = null; this.current = null; if(this._nodeTag == null){ throw new IllegalArgumentException("节点标签名称未赋值"); }else if(this._needTag == null){ throw new IllegalArgumentException("数据标签数据未赋值"); } super.startDocument(); } //节点开头 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if(_nodeTag.equals(localName)){ //实例化一个Map对象 current = new HashMap<String,String>(); } //将当前处理的标签名称保存至preTag中 preTag = localName; } //节点中的文本 @Override public void characters(char[] ch, int start, int length) throws SAXException { //提取标签中的文本 String data = new String(ch,start,length); String dedata = ""; for(String item : this._needTag) { if(item.equals(preTag)) { try { //将数据进行URL解码 dedata = URLDecoder.decode(data,"UTF-8"); } catch (UnsupportedEncodingException e) { dedata = data; }finally{ //将当前的数据放入map对象中 current.put(item, dedata); } return; } } } //节点结束 @Override public void endElement(String uri, String localName, String qName) throws SAXException { if(this._nodeTag.equals(localName)) { //将当前map对象放入ArrayList对象中 this._notics.add(current); current = null; } //将当前标签设置为null preTag = null; } //文档结束 @Override public void endDocument() throws SAXException { current = null; preTag = null; super.endDocument(); } }
相关文章推荐
- 项目开发,我的名字不可能这么可爱——使用XML和Sqlite处理数据
- android应用开发笔记-xml数据资源使用
- android开发入门-2(使用静态变量传递数据)
- Android开发之获取web服务器xml数据
- android开发中eclipse里xml开发的自动提示和使用帮助快捷键提示
- 使用XMLBeans处理XML数据和文档入门 作者:肖菁 (dev2dev ID: powerise) 湖南省长沙铁道学院科创计算机系统集成有限公司软件中心软件工程师
- Android开发本地及网络Mp3音乐播放器(十一)使用Jsoup组件请求网络,并解析音乐数据
- Android应用开发学习笔记之使用Bundle交换数据
- Android开发_Sharedpreferences_存储数据使用方法_完整Demo_AndroidStudio
- iOS开发之网络数据解析--GDataXML解析框架的使用
- 【Android 开发教程】使用Intent传递数据
- 使用XStream注解处理xml的属性及数据集合
- android 开发零起步学习笔记(十五):android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- Android开发必备武器,处理XML的利器——SAX快速上手
- 安卓开发培训(3.2 使用SharedPreferences实现Android数据读写操作)
- Android应用开发SharedPreferences存储数据的使用方法
- android游戏开发框架libgdx的使用(十四)—TiledMap中视角完善和障碍物处理
- xml数据处理--ElementTree模块使用
- Android开发 使用Xutils3请求、解析数据
- xml数据处理--expat模块使用