一、Android开发中三种主要的XML解析方法

在平时的工作和学习中,我们经常需要在android项目中解析XML文件,android为我们提供了三种解析XML的方法,分别是Sax解析、Pull解析和Dom解析,下面简要介绍下这三种解析方法:

SAX解析器:

SAX(Simple API for XML)解析器是一种 基于事件的解析器,它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。
SAX解析器的优点是解析速度快,占用内存少。非常适合在Android移动设备中使用。

DOM解析器:

DOM是 基于树形结构的的节点或信息片段的集合,允许开发人员使用DOM API遍历XML树、检索所需数据。分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息。
由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源。

PULL解析器:

PULL解析器的运行方式和SAX类似,都是 基于事件的模式。不同的是,在PULL解析过程中,我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。 PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器。

二、三种解析方法的代码怎么写

先看要解析的XML文件格式:
这里只放了一个标签,整个xml文件的内容就是由很多这个标签组成的,限于篇幅,这里就不贴上全部文件内容了

SAX解析:

实现Sax解析我们需要继承类DefaultHandler,通过复写其中的characters(), endDocument(), endElement(), startDocument(), startElement()等方法,从而解析出XML文件中的节点信息,首先看MyContentHandler.java,该类继承了DefaultHandler,代码如下:
package com.example.xmlparsetest.sax;import java.util.ArrayList;import java.util.List;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import com.example.xmlparsetest.adapter.MyListAdapter;import com.example.xmlparsetest.bean.CityBean;import android.content.Context;import android.util.Log;import android.widget.ListView;public class MyContentHandler extends DefaultHandler {private String tag = null;private List cityList = new ArrayList();private ListView listView;private Context context;private long startTime;private long endTime;/**构造方法,传入上下文context和ListView,解析文档结束后在ListView上显示解析后的数据*/public MyContentHandler(Context context, ListView listView){this.context = context;this.listView = listView;}/**重要的方法之一,用于获取节点中的数据*/@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {super.characters(ch, start, length);}public List getList(){return cityList;}public long getTime(){return endTime - startTime;}/**重要方法之一*/@Overridepublic void endDocument() throws SAXException {super.endDocument();endTime = System.currentTimeMillis();//解析到文档结束,将数据显示到ListView上listView.setAdapter(new MyListAdapter(context, cityList));}/**重要方法之一*/@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {super.endElement(uri, localName, qName);tag = null;}/**重要方法之一*/@Overridepublic void startDocument() throws SAXException {super.startDocument();startTime = System.currentTimeMillis();Log.e("yubo", "startDocument");}/**重要方法之一*/@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {super.startElement(uri, localName, qName, attributes);//localName是节点名称tag = localName;//匹配到XML文件中的city节点if("city".equals(tag)){CityBean bean = new CityBean();//把节点中的属性取出来放到bean中bean.setQuName(attributes.getValue("quName"));bean.setPyName(attributes.getValue("pyName"));bean.setCityname(attributes.getValue("cityname"));bean.setState1(attributes.getValue("state1"));bean.setState2(attributes.getValue("state2"));bean.setStateDetailed(attributes.getValue("stateDetailed"));bean.setTem1(attributes.getValue("tem1"));bean.setTem2(attributes.getValue("tem2"));bean.setWindState(attributes.getValue("windState"));cityList.add(bean);}}}
上面的代码有些地方做了注释,带有@Override的方法都是复写过的,是Sax解析XML必不可少的方法,下面看上面写的DefaultHandler类怎么用,代码如下:
package com.example.xmlparsetest.dom;import java.util.ArrayList;import java.util.List;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.NodeList;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.widget.ListView;import com.example.xmlparsetest.R;import com.example.xmlparsetest.adapter.MyListAdapter;import com.example.xmlparsetest.bean.CityBean;import com.example.xmlparsetest.utils.FileUtils;public class TestDomActivity extends Activity {private ListView listView;private long startTime;private long endTime;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_list);listView = (ListView) findViewById(R.id.listview);parse();}/**解析XML的主要方法*/private void parse(){List cityList = new ArrayList();try {DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document doc = builder.parse(FileUtils.getFileInputStream(this));startTime = System.currentTimeMillis();//得到文档的根节点Element root = doc.getDocumentElement();//从根节点中选择出节点名为city的子节点,构成一个节点listNodeList nodeList = root.getElementsByTagName("city");//通过循环将每个city节点中的数据解析出来for(int i = 0; i < nodeList.getLength(); i++){CityBean bean = new CityBean();//得到第i个city节点Element element = (Element)nodeList.item(i);//获取city节点中的属性值String quName = element.getAttribute("quName");String pyName = element.getAttribute("pyName");String cityname = element.getAttribute("cityname");String state1 = element.getAttribute("state1");String state2 = element.getAttribute("state2");String stateDetailed = element.getAttribute("stateDetailed");String tem1 = element.getAttribute("tem1");String tem2 = element.getAttribute("tem2");String windState = element.getAttribute("windState");bean.setQuName(quName);bean.setPyName(pyName);bean.setCityname(cityname);bean.setState1(state1);bean.setState2(state2);bean.setStateDetailed(stateDetailed);bean.setTem1(tem1);bean.setTem2(tem2);bean.setWindState(windState);cityList.add(bean);}//计算解析用时并返回给上一个activityendTime = System.currentTimeMillis();Intent intent = new Intent();intent.putExtra("time", endTime - startTime);setResult(301, intent);//在ListView上显示数据MyListAdapter adapter = new MyListAdapter(this, cityList);listView.setAdapter(adapter);} catch (Exception e) {e.printStackTrace();}}}

DOM解析:

DOM解析是将一个文档全部加载到内存中再解析每一个节点的,使用方法如下:
package com.example.xmlparsetest.dom;import java.util.ArrayList;import java.util.List;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.NodeList;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.widget.ListView;import com.example.xmlparsetest.R;import com.example.xmlparsetest.adapter.MyListAdapter;import com.example.xmlparsetest.bean.CityBean;import com.example.xmlparsetest.utils.FileUtils;public class TestDomActivity extends Activity {private ListView listView;private long startTime;private long endTime;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_list);listView = (ListView) findViewById(R.id.listview);parse();}/**解析XML的主要方法*/private void parse(){List cityList = new ArrayList();try {DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document doc = builder.parse(FileUtils.getFileInputStream(this));startTime = System.currentTimeMillis();//得到文档的根节点Element root = doc.getDocumentElement();//从根节点中选择出节点名为city的子节点,构成一个节点listNodeList nodeList = root.getElementsByTagName("city");//通过循环将每个city节点中的数据解析出来for(int i = 0; i < nodeList.getLength(); i++){CityBean bean = new CityBean();//得到第i个city节点Element element = (Element)nodeList.item(i);//获取city节点中的属性值String quName = element.getAttribute("quName");String pyName = element.getAttribute("pyName");String cityname = element.getAttribute("cityname");String state1 = element.getAttribute("state1");String state2 = element.getAttribute("state2");String stateDetailed = element.getAttribute("stateDetailed");String tem1 = element.getAttribute("tem1");String tem2 = element.getAttribute("tem2");String windState = element.getAttribute("windState");bean.setQuName(quName);bean.setPyName(pyName);bean.setCityname(cityname);bean.setState1(state1);bean.setState2(state2);bean.setStateDetailed(stateDetailed);bean.setTem1(tem1);bean.setTem2(tem2);bean.setWindState(windState);cityList.add(bean);}//计算解析用时并返回给上一个activityendTime = System.currentTimeMillis();Intent intent = new Intent();intent.putExtra("time", endTime - startTime);setResult(301, intent);//在ListView上显示数据MyListAdapter adapter = new MyListAdapter(this, cityList);listView.setAdapter(adapter);} catch (Exception e) {e.printStackTrace();}}}

PULL解析:

pull解析的代码也不复杂,直接上代码:
package com.example.xmlparsetest.pull;import java.util.ArrayList;import java.util.List;import org.xmlpull.v1.XmlPullParser;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Xml;import android.widget.ListView;import com.example.xmlparsetest.R;import com.example.xmlparsetest.adapter.MyListAdapter;import com.example.xmlparsetest.bean.CityBean;import com.example.xmlparsetest.utils.FileUtils;public class TestPullActivity extends Activity {private ListView listView;private long startTime;private long endTime;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_list);listView = (ListView) findViewById(R.id.listview);parse();}private void parse(){List cityList = new ArrayList();try {XmlPullParser parser = Xml.newPullParser();parser.setInput(FileUtils.getFileInputStream(this), "UTF-8");//获取事件类型int eventType = parser.getEventType();//根据事件类型做不同的处理,循环条件是没到文件结束while(eventType != XmlPullParser.END_DOCUMENT){switch(eventType){//开始解析文档case XmlPullParser.START_DOCUMENT:startTime = System.currentTimeMillis();break;//开始一个tag标签case XmlPullParser.START_TAG:if("city".equals(parser.getName())){String quName = parser.getAttributeValue(null, "quName");String pyName = parser.getAttributeValue(null, "pyName");String cityname = parser.getAttributeValue(null, "cityname");String state1 = parser.getAttributeValue(null, "state1");String state2 = parser.getAttributeValue(null, "state2");String stateDetailed = parser.getAttributeValue(null, "stateDetailed");String tem1 = parser.getAttributeValue(null, "tem1");String tem2 = parser.getAttributeValue(null, "tem2");String windState = parser.getAttributeValue(null, "windState");CityBean bean = new CityBean();bean.setQuName(quName);bean.setPyName(pyName);bean.setCityname(cityname);bean.setState1(state1);bean.setState2(state2);bean.setStateDetailed(stateDetailed);bean.setTem1(tem1);bean.setTem2(tem2);bean.setWindState(windState);cityList.add(bean);}break;}eventType = parser.next();}//计算解析事件endTime = System.currentTimeMillis();Intent intent = new Intent();intent.putExtra("time", endTime - startTime);setResult(201, intent);} catch (Exception e) {e.printStackTrace();}//在ListView上显示数据MyListAdapter adapter = new MyListAdapter(this, cityList);listView.setAdapter(adapter);}}
可以看到,pull解析类似Sax解析,都有开始文档,开始标签,结束标签,结束文档的事件和对应的处理,不同的地方是,Sax解析已经将事件处理接口写好了,我们写好对应事件的处理代码就行,而pull解析则需要我们自己捕获相应的事件并写处理事件的代码。
下面上两张程序运行时截图:(这里的解析用时不能看出三种解析方式的好坏,毕竟文档的大小有大有小,在平时的开发中,要选择合适的解析方法)

三、一个小小的总结

作为与服务器端交互的数据格式,XML和JSON是平时开发中用得比较多的两种,我个人觉得JSON的解析更简单一些,XML稍微复杂了点,不过这两种数据格式的解析我们都要掌握好嘛,下一篇再讲JSON数据的解析方法。这一篇的源码在这里: 点击下载


更多相关文章

  1. Android(安卓)Architecture Components 之 LiveData
  2. Android(安卓)小项目之--Mini音乐播放器【简单版】(附源码)
  3. OSG for Android新手教程系列(四)——JNI与NDK的使用
  4. Android实训案例(七)——四大组件之一Service初步了解,实现通话录音
  5. 在Android(安卓)中使用KSOAP2调用WebService
  6. 学习Android界面设计的超级利器HierarchyView.bat
  7. Android相机开发——CameraView源码解析
  8. Android(安卓)服务两种启动方式的区别
  9. Android资源String中html标签的使用

随机推荐

  1. android GPS定位和卫星个数(源码)
  2. android IO流 写入 读出
  3. android多线程下载详解
  4. Android(安卓)日期工具类DateUtil
  5. Android(安卓)Studio RadioGroup判断点击
  6. android TV盒子开发遥控器按键的监听
  7. IllegalStateException,PatternSyntaxExce
  8. Android简单的计算控件使用
  9. 彻底解决Android中文乱码
  10. Android(安卓)4.0 UI for Tablet and Han