Android中三种主要的XML解析方法
2014-12-02 10:24
441 查看
一、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文件格式:<city quName="黑龙江" pyName="heilongjiang" cityname="哈尔滨" state1="13" state2="13" stateDetailed="阵雪" tem1="-13" tem2="-19" windState="北风4-5级转3-4级"/>这里只放了一个标签,整个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<CityBean> cityList = new ArrayList<CityBean>(); 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; } /**重要的方法之一,用于获取节点中的数据*/ @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); } public List<CityBean> getList(){ return cityList; } public long getTime(){ return endTime - startTime; } /**重要方法之一*/ @Override public void endDocument() throws SAXException { super.endDocument(); endTime = System.currentTimeMillis(); //解析到文档结束,将数据显示到ListView上 listView.setAdapter(new MyListAdapter(context, cityList)); } /**重要方法之一*/ @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); tag = null; } /**重要方法之一*/ @Override public void startDocument() throws SAXException { super.startDocument(); startTime = System.currentTimeMillis(); Log.e("yubo", "startDocument"); } /**重要方法之一*/ @Override public 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; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list); listView = (ListView) findViewById(R.id.listview); parse(); } /**解析XML的主要方法*/ private void parse(){ List<CityBean> cityList = new ArrayList<CityBean>(); try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(FileUtils.getFileInputStream(this)); startTime = System.currentTimeMillis(); //得到文档的根节点 Element root = doc.getDocumentElement(); //从根节点中选择出节点名为city的子节点,构成一个节点list NodeList 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); } //计算解析用时并返回给上一个activity endTime = 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; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list); listView = (ListView) findViewById(R.id.listview); parse(); } /**解析XML的主要方法*/ private void parse(){ List<CityBean> cityList = new ArrayList<CityBean>(); try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(FileUtils.getFileInputStream(this)); startTime = System.currentTimeMillis(); //得到文档的根节点 Element root = doc.getDocumentElement(); //从根节点中选择出节点名为city的子节点,构成一个节点list NodeList 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); } //计算解析用时并返回给上一个activity endTime = 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; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list); listView = (ListView) findViewById(R.id.listview); parse(); } private void parse(){ List<CityBean> cityList = new ArrayList<CityBean>(); 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数据的解析方法。这一篇的源码在这里:点击下载相关文章推荐
- android中的三种xml解析方法---sax解析,pull解析,dom
- Android开发之XML文件的解析的三种方法
- android xml解析 三种方法比较
- Android中XML解析,保存的三种方法
- Android开发之XML文件的解析的三种方法
- Android编程实现XML解析与保存的三种方法详解
- Android布局解析的三种方法(.xml-->View)
- Android开发之XML文件的解析的三种方法
- Android开发之XML文件的解析的三种方法
- Android中解析XML三种方法
- Android开发之XML文件的解析的三种方法
- Android XML解析三种方法
- Android开发之XML文件的解析的三种方法
- android中三种xml解析及Json解析方法
- Android开发之XML文件的解析的三种方法--转载(三)
- Android中三种解析XML的方法
- Android开发之XML文件的解析的三种方法
- Android开发之XML文件的解析的三种方法
- Android开发之XML文件的解析的三种方法
- Android中XML解析,保存的三种方法