我们在工作中,经常会从服务器获取数据并进行解析,服务器返回的数据有两种:json和xml。json我们可以用gson或者fastjson等优秀的开源框架去进行解析,省去不少麻烦,通常我们只需要把bean设计出来,然后调用一句话就可以解析成功了。而解析xml数据,我们得去一个标签一个标签的去比较,修改起来也非常麻烦,比如我们现在不需要某一个标签上的数据了,我们还得去把代码中那一行给删除,如果我们的需求又变了,现在又需要加上某个标签的数据,那只能再到代码中把相应代码加上,这样非常麻烦,这篇文章我们将介绍如何设计我们自己的xml解析框架,做到可以和gson一样,只需要关心bean的结构,调用一句代码就可以解析成功。

首先我们先来分析一下服务器返回回来的xml数据的格式,然后进行设计。我的数据是从聚合数据上面得到的。

<?xml version="1.0" encoding="utf-8"?>
查询成功NBA2014-2015赛季_火箭队赛程赛果10-2508:0087-96马刺http://nba.sports.sina.com.cn/team.php?id=24火箭http://nba.sports.sina.com.cn/team.php?id=10视频集锦http://video.sina.com.cn/z/sports/k/nba/141025sashou/数据统计http://nba.sports.sina.com.cn/look_scores.php?id=2014102410新闻报道http://sports.sina.com.cn/nba/2014-10-25/10267382993.shtml10-2910:30108-90火箭http://nba.sports.sina.com.cn/team.php?id=10湖人http://nba.sports.sina.com.cn/team.php?id=13视频集锦http://video.sina.com.cn/z/sports/k/nba/141029houlal/数据统计http://nba.sports.sina.com.cn/look_scores.php?id=2014102813新闻报道http://sports.sina.com.cn/nba/2014-10-29/13367388047.shtml10-3009:00104-93火箭http://nba.sports.sina.com.cn/team.php?id=10爵士http://nba.sports.sina.com.cn/team.php?id=26视频集锦http://video.sina.com.cn/z/sports/k/nba/141030houuta/数据统计http://nba.sports.sina.com.cn/look_scores.php?id=2014102926新闻报道http://sports.sina.com.cn/nba/2014-10-30/11267389310.shtml11-0208:00VS凯尔特人http://nba.sports.sina.com.cn/team.php?id=2火箭http://nba.sports.sina.com.cn/team.php?id=10文字直播http://sports.sina.com.cn/nba/live.html?id=201411011011-0408:00VS火箭http://nba.sports.sina.com.cn/team.php?id=1076人http://nba.sports.sina.com.cn/team.php?id=20文字直播http://sports.sina.com.cn/nba/live.html?id=201411032011-0508:30VS火箭http://nba.sports.sina.com.cn/team.php?id=10热火http://nba.sports.sina.com.cn/team.php?id=14文字直播http://sports.sina.com.cn/nba/live.html?id=2014110414http://nba.sports.sina.com.cn/team_match.php?id=10
            火箭队完整赛程http://nba.sports.sina.com.cn/showtv.php
            电视转播表0
1.我们使用xml的pull解析方法,解析的过程是从第一个开始标签顺序往下直到最后一个结束标签。先确定我们需要哪些标签上的数据。reason和title上面有数据,我们想要得到。然后就是一堆item,每个item里面都有一些数据,我们想要得到。
2.分析结构:item一看就知道是要存储在一个list里面的,每个item里面的标签也都是一样的,只是数据不一样而已,所以我们要设计一个ListBean,用来保存item里面的数据,然后放到一个ArrayList里面。这样可以将所有的item都保存起来。

public class ListBean {public String c1;public String c2;public String c3;public String c4R;public String c4T1;public String c4T1URL;public String c4T2;public String c4T2URL;public String c51;public String c52;public String c52Link;public String c53;public String c53Link;public String c54;public String c54Link;@Overridepublic String toString() {return "ListBean [c1=" + c1 + ", c2=" + c2 + ", c3=" + c3 + ", c4R="+ c4R + ", c4T1=" + c4T1 + ", c4T1URL=" + c4T1URL + ", c4T2="+ c4T2 + ", c4T2URL=" + c4T2URL + ", c51=" + c51 + ", c52="+ c52 + ", c52Link=" + c52Link + ", c53=" + c53 + ", c53Link="+ c53Link + ", c54=" + c54 + ", c54Link=" + c54Link + "]";}}

再看reason和title,这两个标签也应该保存在一个bean中,我们在设计一个Bean

public class Bean {public String reason;public String title;@Overridepublic String toString() {return "Bean [reason=" + reason + ", title=" + title + "]";}}

整个xml数据的结构为一个bean和一个list的结构:bean:reason和title    list:所有的item
3.我们再设计一个最终结果的实体类,一个bean和一个list

public class ResultBeanAndList {public Object bean;public ArrayList list;public Object getBean() {return bean;}public void setBean(Object bean) {this.bean = bean;}public ArrayList getList() {return list;}public void setList(ArrayList list) {this.list = list;}@Overridepublic String toString() {return "ResultBeanAndList [bean=" + bean + ", list=" + list + "]";}
}

其中的T是一个泛型,里面传入的是item的实体类,即这个例子中的ListBean
4.在解析的过程中是从第一个标签顺序向后解析的,我们必须得让parser知道:什么时候是外层的Bean,什么时候是内层的ListBean,什么时候将ListBean加入到list中。其实很简单,当parser解析到<root>的时候,我们就让Bean实例化出来,当解析到</root>的时候,就将Bean保存到ResultBeanAndList中。当parser解析到<item>的时候,我们将ListBean实例化出来,当解析到</list>的时候,将ListBean加入到ResultBeanAndList中。

public class XmlUtils {/*** 解析一个bean和一个list的xml文件结构的方法* @param parser 解析者* @param listRoot 内层ListBean需要实例化对象的一个标识* @param listClazz ListBean.class* @param beanRoot 外层Bean需要实例化对象的一个标识* @param beanClazz Bean.class* @return 一个bean和一个list的结果* @throws Exception*/public static  ResultBeanAndList getBeanByParseXml(XmlPullParser parser , String listRoot , Class listClazz ,String beanRoot , Class beanClazz) throws Exception{//最后结果ResultBeanAndList result = null;//list  存放一堆itemArrayList list = null;//内层ListBeanT t = null;//外层BeanT1 bean = null;//一个计数器int count = 0 ;try {//获得当前标签类型int eventType = parser.getEventType();//如果不是xml文件结束标签,则一个一个向下解析while(eventType != XmlPullParser.END_DOCUMENT){switch (eventType) {//如果是xml文件开始标签,则初始化一些数据case XmlPullParser.START_DOCUMENT://最后的结果result = new ResultBeanAndList();//listlist = new ArrayList();//将list加入到result中,当前list是空的,等后面加入了数据后,就不是空了result.setList(list);break;//开始标签case XmlPullParser.START_TAG://获得标签的名字String tagName = parser.getName();//如果内层的ListBean已经实例化出来的话if (t != null) {try {//判断当前标签在没在ListBean的属性中Field field = listClazz.getField(tagName);//如果ListBean中有当前标签if (field != null) {//计数器+1count++;//将取出来的值赋给ListBean中对应的属性field.set(t, parser.nextText());}} catch (Exception e) {//如果ListBean中没有当前标签,则会直接跳到这里,什么都不执行,然后再继续往下走}//如果外层的Bean已经实例化出来的话}else if (bean != null) {try {//判断当前标签在没在Bean的属性中Field field = beanClazz.getField(tagName);//如果Bean中有当前标签if (field != null) {//计数器+1count++;//将取出来的值赋给Bean中对应的属性field.set(bean, parser.nextText());}} catch (Exception e) {//如果Bean中没有当前标签,则会直接跳到这里,什么都不执行,然后再继续往下走}}//如果当前标签为我们传入的内层根标签,说明ListBean需要实例化出来了if (tagName.equals(listRoot)) {//将ListBean实例化出来t = listClazz.newInstance();}//如果当前标签为我们传入的内层根标签,说明Bean需要实例化出来了if (tagName.equals(beanRoot)) {//将Bean实例化出来bean = beanClazz.newInstance();}break;//结束标签case XmlPullParser.END_TAG://如果当前标签为if (listRoot.equalsIgnoreCase(parser.getName())) {//如果ListBean不为空if (t != null) {//保存到list中,同时也保存到了result中,因为list已经是保存在result中了,//只不过刚才没有值,现在有值了list.add(t);//并且把ListBean置空,因为后续还有好多个itemt = null;}//如果当前标签为}else if (beanRoot.equalsIgnoreCase(parser.getName())) {//将Bean保存到result中result.setBean(bean);}break;}//移动到下一个标签eventType = parser.next();}} catch (Exception e) {e.printStackTrace();}//如果计数器为0说明没有解析到任何数据if (count == 0) {//将result置空就可以了result = null;}//将result返回return result;}
}

5.我们使用基于Volley的自定义Request获取xml数据,关于如何自定义Request请参见Android网络框架-Volley(五) 使用Volley发送自定义Request

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);String url = "http://op.juhe.cn/onebox/basketball/team";//我们使用基于Volley自定义的XMLRequest获取xml数据,post方法XMLRequest xmlRequest = new XMLRequest(Method.POST, url, new Listener() {@Overridepublic void onResponse(XmlPullParser response) {try {//我们看到第二个参数 “listRoot”我们传入的是item。第三个参数是ListBean.class//第四个参数“beanRoot”我们传入的是root。第四个参数是Bean.classResultBeanAndList result = XmlUtils.getBeanByParseXml(response, "item", ListBean.class, "root", Bean.class);} catch (Exception e) {e.printStackTrace();}}}, new Response.ErrorListener(){@Overridepublic void onErrorResponse(VolleyError error) {}}){//聚合数据文档要求需要传递以下参数,大家可以到聚合数据去申请一下,就会得到一个key@Overrideprotected Map getParams() throws AuthFailureError {Map params = new HashMap();params.put("key","14acc11b5dd32beb57b90181c80c76b2 ");params.put("team", "火箭");params.put("dtype", "xml");return params;}};//将request加入到requestQueue中AppController.getInstance().addToRequestQueue(xmlRequest);}
}

6.从xml获取的数据如下:

最后结果result中的数据如下

总结:
1.代码中的注释为了避免大家混淆,我都用的这个例子中的实体类的名字,其实我们定义了泛型,实体类可以传入任何一个类,这个根据我们实际的需要,设计我们需要的实体类就可以了。比如我们不需要title这个数据了,那我们直接将Bean中的title属性删除就可以了,如果我们在Bean中加入了一个不相关的属性,例如Public String abc;
我们也不需要担心出错,通过Field field = listClazz.getField(tagName);如果xml文件中没有<abc>这个标签的话,就会直接跳到catch里,接着会向后执行,不会出任何错误。
2.这个例子中的xml文件是一个bean和一个list的结构,如果是一个bean和两个list的结构,我们就需要再按照此思路设计一个解析方法, 如果是只有一个bean的结构那更简单了,我们在工作中,遇到一种结构,就将其设计出来加入到XmlUtils中。这样就形成了一款我们自己的xml解析框架,以后再有相同结构的xml文件,直接设计实体类即可。

Android自己动手打造XML解析框架相关推荐

  1. 制衣厂普工小伙用java代码写的xml解析框架

    xml解析框架,这个框架也可以解析html,是我自己写的xml解析技术,花费我很多的时间,我在工厂做这个工作来维持生计↓↓↓↓↓↓↓↓ 哈哈哈,开个玩笑,下面这张图片才是我,这张图片是主管拍的 平均月 ...

  2. Android开发学习之Xml解析归纳

    在程序开发中,有两种语言是和平台无关的,它们就是Xml和Json,因此,作为在不同平台间传递信息的Xml和Json在Android中同样扮演者重要的角色,那么今天我们就来一起学习Android中Xml ...

  3. 超级简洁的xml解析框架:TBXML

    就xml解析来讲,目前用过的最简洁,速度最快的当属tbxml,是基于C框架的所以直接拿在iPhone上用了. 先说下用法,把tbxml的4个文件拖入class,然后为工程添加libz.dylib框架即 ...

  4. Android开发系列之XML解析

     xml文件存储是常用的数据存储方式,xml解析常用的有SAX解析.DOM解析.PULL解析等.本篇讲述xml的格式,xml的写入方式以及xml的解析.   .xml格式 <cartons> ...

  5. Android使用SAX实现XML解析,使用text/xml格式与后台交互

    这篇博文正式发表于2015-02-16 14:20,现在显示的创建时间2015-02-05 10:07是当初写草稿的时间 一.SAX解析XML 1,首先展示一下要写入以及解析的xml的文件格式: &l ...

  6. Android,XML解析

    XML解析三种方式 DOM 通用性强,它会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树.检索所需的数据: 简单直观,但需要将文档读取到内存,并不太适合移动设备: SAX ...

  7. CC00119.bigdatajava——|JavaMySQL.XML.V10|——|MySQL.v10|常见XML解析器|DOM4API介绍|

    一.XML常见的解析器 ### --- XML常见的解析器~~~ # 解析器:就是根据不同的解析方式提供的具体实现.有的解析器操作过于繁琐, --> 为了方便开发人员,有提供易于操作的解析开发包 ...

  8. xml解析: dom4j

    目录 一.XML解析 1.概述 2.解析方式和解析器 二.Dom4j的基本使用 1.解析原理 2.基本使用 2.常用方法 (1)SaxReader对象 (2)Document对象 (3)Element ...

  9. 常用 XML 解析技术

    现在的软件项目都不是独立的一个项目,都是多系统协调工作.这样的话就涉及到系统间的通讯,通讯就会跟报文传输挂上关系.系统间使用怎样的报文格式进行通讯呢?有的使用固定长度格式报文:有的使用变长格式报文:有 ...

  10. UsageStatsService之坑:一个XML解析异常导致的开机动画死循环

    文章目录 UsageStatsService之坑:一个XML解析异常导致的开机动画死循环 声明 问题说明 日志排查 猜想和验证 问题定位 插曲 -- XML的解析 问题修复 杯弓蛇影 参考资料 修改说 ...

最新文章

  1. 想从事单片机工作,C语言要达到什么水平?
  2. win 10升级后不能访问服务器文件夹,Win10打开某些文件夹出现“无法访问”的解决方法...
  3. 6. Qt 信号与信号槽 (6)- QObject::connect
  4. Thinkphp5.0快速入门笔记(1)
  5. 【spring相关面试题摘录】
  6. 《ASP.NET Core 微服务实战》-- 读书笔记(第11章)
  7. 初级程序员需要接触好的架构代码
  8. 1-3 交换变量(算法竞赛入门经典)
  9. vs winform常用函数_使用.net core3.0 正式版创建Winform程序
  10. dede index.php权限_织梦实现全站动态,限制只有会员才能查看
  11. 本地像服务器传文件,本地向服务器传送文件
  12. django进阶05中间件
  13. linux yum提示Loaded plugins: fastestmirror, security错误的解决方法
  14. zabbix中文乱码的解决办法
  15. redis php 性能测试工具,Php-Redis安装测试笔记
  16. android camera textureview,Android SDK – camera2 – 在TextureView上绘制矩...
  17. 关于烧写ESP8285核心板的相关事项
  18. 1小时学会不打代码制作一个网页精美简历(1)
  19. sqliteman安装时出现The following packages have unmet dependencies: libqtgui4 : Depends: libpng12-0错误
  20. JAVA利用jsoup爬取百度热点信息

热门文章

  1. 04、CONSTANT-ROUND CZK PROOFS for NP--Alon Rosen[对于NP的常数轮CZK证明]
  2. 局域网内ip冲突引起的怪异现象
  3. python爬取天天基金历史净值_python爬取天天基金网全部基金的历史全部净值
  4. 阿里P7级别面试经验总结,面试心得体会
  5. “拖延症”的良方——对于追求完美,自制力差,情绪化的人很受用。 【谨以此文共勉。】 来源: 胡野的日志
  6. VBA--遍历所有工作表_冻结首行_无视工作表长度_and_所在单元格位置
  7. 心中有佛,看谁都是佛;心中有屎,看谁都是屎。
  8. 徐家骏:我在华为工作十年的感悟
  9. CAS (4) —— CAS浏览器SSO访问顺序图详解(CAS Web Flow Diagram by Example)
  10. 怎么制作GIF高清动态表情包