Android中Xml解析实战
来源:互联网 发布:专业八字算命软件 编辑:程序博客网 时间:2024/06/05 19:42
在Android中,常见的XML解析器分别为DOM解析器、SAX解析器和PULL解析器,下面,我将一一向大家详细介绍。
DOM解析器:
DOM是基于树形结构的的节点或信息片段的集合,允许开发人员使用DOM API遍历XML树、检索所需数据。分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息。Android完全支持DOM 解析。利用DOM中的对象,可以对XML文档进行读取、搜索、修改、添加和删除等操作。
DOM的工作原理:使用DOM对XML文件进行操作时,首先要解析文件,将文件分为独立的元素、属性和注释等,然后以节点树的形式在内存中对XML文件进行表示,就可以通过节点树访问文档的内容,并根据需要修改文档——这就是DOM的工作原理。
DOM实现时首先为XML文档的解析定义一组接口,解析器读入整个文档,然后构造一个驻留内存的树结构,这样代码就可以使用DOM接口来操作整个树结构。
由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源。 当然,如果XML文件的内容比较小,采用DOM是可行的。
常用的DOM接口和类:
Document:该接口定义分析并创建DOM文档的一系列方法,它是文档树的根,是操作DOM的基础。 Element:该接口继承Node接口,提供了获取、修改XML元素名字和属性的方法。Node:该接口提供处理并获取节点和子节点值的方法。NodeList:提供获得节点个数和当前节点的方法。这样就可以迭代地访问各个节点。DOMParser:该类是Apache的Xerces中的DOM解析器类,可直接解析XML文件。
下面是DOM的解析流程:
采用DOM解析时具体处理步骤是:1 首先利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例2 然后利用DocumentBuilderFactory创建DocumentBuilder3 然后加载XML文档(Document),4 然后获取文档的根结点(Element),5 然后获取根结点中所有子节点的列表(NodeList),6 然后使用再获取子节点列表中的需要读取的结点。
Xml文件内容如下:
<?xml version="1.0" encoding="utf-8"?><channel><item id="0" url="http://www.baidu.com">百度</item><item id="1" url="http://www.qq.com">腾讯</item><item id="2" url="http://www.sina.com.cn">新浪</item><item id="3" url="http://www.taobao.com">淘宝</item></channel>
Java代码如下:
public class DomPraserDemo extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); SimpleAdapter adapter = new SimpleAdapter(this, getData(), R.layout.list, new String[] { "id", "name" }, new int[] { R.id.textId, R.id.textName }); setListAdapter(adapter); } private List<Map<String, String>> getData() { List<Map<String, String>> list = new ArrayList<Map<String, String>>(); InputStream stream = getResources().openRawResource(R.raw.channels); List<channel> channlist = getChannelList(stream); for (int i = 0; i < channlist.size(); i++) { Map<String, String> map = new HashMap<String, String>(); channel chann = (channel) channlist.get(i); map.put("id", chann.getId()); map.put("url", chann.getUrl()); map.put("name", chann.getName()); list.add(map); } return list; } public static List<channel> getChannelList(InputStream stream) { List<channel> list=new ArrayList<channel>(); //得到 DocumentBuilderFactory 对象, 由该对象可以得到 DocumentBuilder 对象 DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); try { //得到DocumentBuilder对象 DocumentBuilder builder=factory.newDocumentBuilder(); //得到代表整个xml的Document对象 Document document=builder.parse(stream); //得到 "根节点" Element root=document.getDocumentElement(); //获取根节点的所有items的节点 NodeList items=root.getElementsByTagName("item"); //遍历所有节点 for(int i=0;i<items.getLength();i++) { channel chann=new channel(); Element item=(Element)items.item(i); chann.setId(item.getAttribute("id")); chann.setUrl(item.getAttribute("url")); chann.setName(item.getFirstChild().getNodeValue()); list.add(chann); } } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; }}
SAX解析器:
SAX(Simple API for XML)解析器是一种基于事件的解析器,事件驱动的流式解析方式是,从文件的开始顺序解析到文档的结束,不可暂停或倒退。它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。
SAX解析器的优点是解析速度快,占用内存少。非常适合在Android移动设备中使用。
SAX的工作原理:SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
下面是SAX的解析流程:
采用SAX解析时具体处理步骤是:1 创建SAXParserFactory对象2 根据SAXParserFactory.newSAXParser()方法返回一个SAXParser解析器3 根据SAXParser解析器获取事件源对象XMLReader4 实例化一个DefaultHandler对象5 连接事件源对象XMLReader到事件处理类DefaultHandler中6 调用XMLReader的parse方法从输入源中获取到的xml数据7 通过DefaultHandler返回我们需要的数据集合。
解析器主要代码:
private List<channel> getChannelList() throws ParserConfigurationException, SAXException, IOException { //实例化一个SAXParserFactory对象 SAXParserFactory factory=SAXParserFactory.newInstance(); SAXParser parser; //实例化SAXParser对象,创建XMLReader对象,解析器 parser=factory.newSAXParser(); XMLReader xmlReader=parser.getXMLReader(); //实例化handler,事件处理器 SAXPraserHelper helperHandler=new SAXPraserHelper(); //解析器注册事件 xmlReader.setContentHandler(helperHandler); //读取文件流 InputStream stream=getResources().openRawResource(R.raw.channels); InputSource is=new InputSource(stream); //解析文件 xmlReader.parse(is); return helperHandler.getList(); }
Handler代码:
public class SAXPraserHelper extends DefaultHandler{ final int ITEM = 0x0005; List<channel> list; channel chann; int currentState = 0; public List<channel> getList() { return list; } @Override public void startDocument() throws SAXException { list = new ArrayList<channel>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { chann = new channel(); if(localName.equals("item")){ for(int i = 0 ;i < attributes.getLength(); i++){ if(attributes.getLocalName(i).equals("id")){ chann.setId(attributes.getValue(i)); }else if(attributes.getLocalName(i).equals("url")){ chann.setUrl(attributes.getValue(i)); } } currentState = ITEM; return; } currentState = 0; return; } @Override public void characters(char[] ch, int start, int length) throws SAXException { if(currentState != 0){ String value = String.valueOf(ch,start,length); chann.setName(value); currentState = 0; } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if(localName.equals("item")){ list.add(chann); } }}
PULL解析器:
Android并未提供对Java StAX API的支持。但是,Android附带了一个pull解析器,其工作方式类似于StAX。它允许用户的应用程序代码从解析器中获取事件,这与SAX解析器自动将事件推入处理程序相反。
PULL解析器的运行方式和SAX类似,都是基于事件的模式。不同的是,在PULL解析过程中返回的是数字,且我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。
PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器,Android官方推荐开发者们使用Pull解析技术。Pull解析技术是第三方开发的开源技术,它同样可以应用于JavaSE开发。
PULL 的工作原理:XML pull提供了开始元素和结束元素。当某个元素开始时,我们可以调用parser.nextText从XML文档中提取所有字符数据。当解释到一个文档结束时,自动生成EndDocument事件。
下面是PULL的解析流程:
下面是PULL解析XML的过程:读取到xml的声明返回 START_DOCUMENT;读取到xml的结束返回 END_DOCUMENT ;读取到xml的开始标签返回 START_TAG读取到xml的结束标签返回 END_TAG读取到xml的文本返回 TEXT
解析器主要代码:
private List<Map<String, String>> getData() { List<Map<String,String>> list =new ArrayList<Map<String, String>>(); XmlResourceParser xrp = getResources().getXml(R.xml.channels); try{ while (xrp.getEventType() != XmlPullParser.END_DOCUMENT){ if(xrp.getEventType() == XmlPullParser.START_TAG){ String tagName = xrp.getName(); if(tagName.equals("item")) { Map<String,String> map =new HashMap<String, String>(); String id = xrp.getAttributeValue(null,"id"); map.put("id",id); String url = xrp.getAttributeName(1); map.put("url", url); String name = xrp.nextText(); map.put("name", name); list.add(map); } } xrp.next(); } }catch (XmlPullParserException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return list; }
SAX、DOM、PULL的比较
- 内存占用
这是一个根本性问题。由于Android手机性能相对于现在的应用操作还是有限的,程序对内存的占用直接影响到了解析XML的速度。在这点上,SAX、Pull以它们比DOM占用更少的内存的解析方式,更适合于Android手机开发。 - 编程方式
SAX采用事件驱动,在相应事件触发的时候,会调用用户编写好的方法。也就是说,每解析一类XML,就要编写一个新的适合该类XML的处理类。这显然不是一个好的解决办法,尽管其在解析速度上是那么优秀。而这点,DOM因为是W3C的规范。所以被更多程序员所知道和使用。所以在开发过程中,没有太大困难。Pull虽然属于一个小众的,甚至是不为人知的解析器,但是通过上面对其介绍和示例,我们应该能看出它的简洁性。 - 访问与修改
由于采用的是流式解析,这就说明它们不能像DOM那样随机访问,XML的其中任意一个节点。并且,SAX并没有提供对文档中加节点的API,更没有删除,修改文档内容的方法。 - 访问方式
这是产生它们解析快慢的根本原因。如果把SAX和Pull比喻成一目十行,很快但是是走马观花的阅读方式的话,那么DOM就是逐字逐句的阅读,很慢,但是是过目不忘。这里还要需要注意的是,SAX,Pull解析的方式是同步的,即解析器读到哪里,就对哪里进行处理。而DOM是已经将文件解析好后,供用户提取XML中感兴趣的信息。
总结:
出于对内存占用的考虑,推荐使用SAX或者Pull来工作。可是根据它们工作的原理:如果只是需要XML最后的几个节点的相关信息,或者出现反复检索XML文件的情况。那么基本上三者在性能上就没有什么差异,反而在这时,SAX的处理类会使程序显得比其他的实现方式显得臃肿。所以,想做一个高性能的Android软件,还是要多分析,选择合适的工具,才能发挥它的作用。
源码
转自此处
- Android中Xml解析实战
- XML---Android中解析XML .
- XML - Android中解析XML
- Android中解析XML
- android中xml解析
- Android中XML解析
- Android中解析XML
- Android中解析XML
- Android中解析XML
- Android中解析XML
- Android中解析XML
- android中解析xml
- Android中解析XML
- Android中解析XML
- Android中解析XML
- Android中解析XML
- Android中解析XML
- Android中解析XML
- 为PHP安装Memcached扩展连接Memcached
- sleep()和wait()的区别
- workspace里面设置的日历,在studio里面为什么加载不出来?
- 响应式开发架构
- 苹果开发之Cocoa编程(第三版) 第5章 Target/Action
- Android中Xml解析实战
- 不常见的事件
- EasyUI获取页面属性
- Android数据传输加密(二):AES加密
- 特征选择之支持向量机递归特征消除(SVM-RFE)
- Mycat从入门到放弃
- huffman编码的实现与详解
- MyBatis返回类型改如何选择?实体类 or Map。
- iOS实战——开发实战过程中的点点滴滴