标签:
我们在工作中,经常会从服务器获取数据并进行解析,服务器返回的数据有两种:json和xml。json我们可以用gson或者fastjson等优秀的开源框架去进行解析,省去不少麻烦,通常我们只需要把bean设计出来,然后调用一句话就可以解析成功了。而解析xml数据,我们得去一个标签一个标签的去比较,修改起来也非常麻烦,比如我们现在不需要某一个标签上的数据了,我们还得去把代码中那一行给删除,如果我们的需求又变了,现在又需要加上某个标签的数据,那只能再到代码中把相应代码加上,这样非常麻烦,这篇文章我们将介绍如何设计我们自己的xml解析框架,做到可以和gson一样,只需要关心bean的结构,调用一句代码就可以解析成功。
首先我们先来分析一下服务器返回回来的xml数据的格式,然后进行设计。我的数据是从聚合数据上面得到的。
<?xml version="1.0" encoding="utf-8"?> <root> <reason>查询成功</reason> <result> <title>NBA2014-2015赛季_火箭队赛程赛果</title> <list> <item> <c1></c1> <c2>10-25</c2> <c3>08:00</c3> <c4R>87-96</c4R> <c4T1>马刺</c4T1> <c4T1URL>http://nba.sports.sina.com.cn/team.php?id=24</c4T1URL> <c4T2>火箭</c4T2> <c4T2URL>http://nba.sports.sina.com.cn/team.php?id=10</c4T2URL> <c51></c51> <c52>视频集锦</c52> <c52Link>http://video.sina.com.cn/z/sports/k/nba/141025sashou/</c52Link> <c53>数据统计</c53> <c53Link>http://nba.sports.sina.com.cn/look_scores.php?id=2014102410</c53Link> <c54>新闻报道</c54> <c54Link>http://sports.sina.com.cn/nba/2014-10-25/10267382993.shtml</c54Link> </item> <item> <c1></c1> <c2>10-29</c2> <c3>10:30</c3> <c4R>108-90</c4R> <c4T1>火箭</c4T1> <c4T1URL>http://nba.sports.sina.com.cn/team.php?id=10</c4T1URL> <c4T2>湖人</c4T2> <c4T2URL>http://nba.sports.sina.com.cn/team.php?id=13</c4T2URL> <c51></c51> <c52>视频集锦</c52> <c52Link>http://video.sina.com.cn/z/sports/k/nba/141029houlal/</c52Link> <c53>数据统计</c53> <c53Link>http://nba.sports.sina.com.cn/look_scores.php?id=2014102813</c53Link> <c54>新闻报道</c54> <c54Link>http://sports.sina.com.cn/nba/2014-10-29/13367388047.shtml</c54Link> </item> <item> <c1></c1> <c2>10-30</c2> <c3>09:00</c3> <c4R>104-93</c4R> <c4T1>火箭</c4T1> <c4T1URL>http://nba.sports.sina.com.cn/team.php?id=10</c4T1URL> <c4T2>爵士</c4T2> <c4T2URL>http://nba.sports.sina.com.cn/team.php?id=26</c4T2URL> <c51></c51> <c52>视频集锦</c52> <c52Link>http://video.sina.com.cn/z/sports/k/nba/141030houuta/</c52Link> <c53>数据统计</c53> <c53Link>http://nba.sports.sina.com.cn/look_scores.php?id=2014102926</c53Link> <c54>新闻报道</c54> <c54Link>http://sports.sina.com.cn/nba/2014-10-30/11267389310.shtml</c54Link> </item> <item> <c1></c1> <c2>11-02</c2> <c3>08:00</c3> <c4R>VS</c4R> <c4T1>凯尔特人</c4T1> <c4T1URL>http://nba.sports.sina.com.cn/team.php?id=2</c4T1URL> <c4T2>火箭</c4T2> <c4T2URL>http://nba.sports.sina.com.cn/team.php?id=10</c4T2URL> <c51></c51> <c52>文字直播</c52> <c52Link>http://sports.sina.com.cn/nba/live.html?id=2014110110</c52Link> <c53></c53> <c53Link></c53Link> <c54></c54> <c54Link></c54Link> </item> <item> <c1></c1> <c2>11-04</c2> <c3>08:00</c3> <c4R>VS</c4R> <c4T1>火箭</c4T1> <c4T1URL>http://nba.sports.sina.com.cn/team.php?id=10</c4T1URL> <c4T2>76人</c4T2> <c4T2URL>http://nba.sports.sina.com.cn/team.php?id=20</c4T2URL> <c51></c51> <c52>文字直播</c52> <c52Link>http://sports.sina.com.cn/nba/live.html?id=2014110320</c52Link> <c53></c53> <c53Link></c53Link> <c54></c54> <c54Link></c54Link> </item> <item> <c1></c1> <c2>11-05</c2> <c3>08:30</c3> <c4R>VS</c4R> <c4T1>火箭</c4T1> <c4T1URL>http://nba.sports.sina.com.cn/team.php?id=10</c4T1URL> <c4T2>热火</c4T2> <c4T2URL>http://nba.sports.sina.com.cn/team.php?id=14</c4T2URL> <c51></c51> <c52>文字直播</c52> <c52Link>http://sports.sina.com.cn/nba/live.html?id=2014110414</c52Link> <c53></c53> <c53Link></c53Link> <c54></c54> <c54Link></c54Link> </item> </list> <more1> <link>http://nba.sports.sina.com.cn/team_match.php?id=10</link> <txt>火箭队完整赛程</txt> </more1> <more2> <link>http://nba.sports.sina.com.cn/showtv.php</link> <txt>电视转播表</txt> </more2> </result> <error_code>0</error_code> </root>
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; @Override public 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; @Override public String toString() { return "Bean [reason=" + reason + ", title=" + title + "]"; } }
public class ResultBeanAndList<T> { public Object bean; public ArrayList<T> list; public Object getBean() { return bean; } public void setBean(Object bean) { this.bean = bean; } public ArrayList<T> getList() { return list; } public void setList(ArrayList<T> list) { this.list = list; } @Override public String toString() { return "ResultBeanAndList [bean=" + bean + ", list=" + list + "]"; } }
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 <T,T1> ResultBeanAndList<T> getBeanByParseXml(XmlPullParser parser , String listRoot , Class<T> listClazz ,String beanRoot , Class<T1> beanClazz) throws Exception{ //最后结果 ResultBeanAndList<T> result = null; //list 存放一堆item ArrayList<T> list = null; //内层ListBean T t = null; //外层Bean T1 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<T>(); //list list = new ArrayList<T>(); //将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) { //计数器+1 count++; //将取出来的值赋给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) { //计数器+1 count++; //将取出来的值赋给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: //如果当前标签为</item> if (listRoot.equalsIgnoreCase(parser.getName())) { //如果ListBean不为空 if (t != null) { //保存到list中,同时也保存到了result中,因为list已经是保存在result中了, //只不过刚才没有值,现在有值了 list.add(t); //并且把ListBean置空,因为后续还有好多个item t = null; } //如果当前标签为</root> }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 { @Override protected 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<XmlPullParser>() { @Override public void onResponse(XmlPullParser response) { try { //我们看到第二个参数 “listRoot”我们传入的是item。第三个参数是ListBean.class //第四个参数“beanRoot”我们传入的是root。第四个参数是Bean.class ResultBeanAndList<ListBean> result = XmlUtils.getBeanByParseXml(response, "item", ListBean.class, "root", Bean.class); } catch (Exception e) { e.printStackTrace(); } } }, new Response.ErrorListener(){ @Override public void onErrorResponse(VolleyError error) { } }){ //聚合数据文档要求需要传递以下参数,大家可以到聚合数据去申请一下,就会得到一个key @Override protected Map<String, String> getParams() throws AuthFailureError { Map<String, String> params = new HashMap<String, String>(); params.put("key","14acc11b5dd32beb57b90181c80c76b2 "); params.put("team", "火箭"); params.put("dtype", "xml"); return params; } }; //将request加入到requestQueue中 AppController.getInstance().addToRequestQueue(xmlRequest); } }
6.从xml获取的数据如下:
标签:
原文地址:http://www.cnblogs.com/feng-de-wei-xiao/p/4663731.html