Android之解析XML总结(SAX、Pull、Dom三种方式)

        常见的解析xml的方式有一下三种:SAX、Pull、Dom解析方式。最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),今天对android解析xml的这三种方式进行一次总结。

         今天解析的xml示例(channels.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>

一、使用sax方式解析

 基础知识:

     这种方式解析是一种基于事件驱动的api,有两个部分,解析器和事件处理器,解析器就是XMLReader接口,负责读取XML文档,和向事件处理器发送事件(也是事件源),事件处理器ContentHandler接口,负责对发送的事件响应和进行XML文档处理。

     下面是ContentHandler接口的常用方法

     public abstract void characters (char[] ch, int start, int length)

      这个方法来接收字符块通知,解析器通过这个方法来报告字符数据块,解析器为了提高解析效率把读到的所有字符串放到一个字符数组(ch)中,作为参数传递给character的方法中,如果想获取本次事件中读取到的字符数据,需要使用start和length属性。

    public abstract void startDocument () 接收文档开始的通知

     public abstract void endDocument () 接收文档结束的通知

    public abstract void startElement (String uri, String localName, String qName, Attributes atts) 接收文档开始的标签

    public abstract void endElement (String uri, String localName, String qName) 接收文档结束的标签

    在一般使用中为了简化开发,在org.xml.sax.helpers提供了一个DefaultHandler类,它实现了ContentHandler的方法,我们只想继承DefaultHandler方法即可。

   另外SAX解析器提供了一个工厂类:SAXParserFactory,SAX的解析类为SAXParser 可以调用它的parser方法进行解析。

   看了些基础以后开始上代码吧(核心代码,下载代码在附件)

public class SAXPraserHelper extends DefaultHandler {final int ITEM = 0x0005;List<channel> list;channel chann;int currentState = 0;public List<channel> getList() {return list;}/** 接口字符块通知
*/@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {// TODO Auto-generated method stub
// super.characters(ch, start, length);String theString = String.valueOf(ch, start, length);if (currentState != 0) {chann.setName(theString);currentState = 0;}return;}/** 接收文档结束通知
*/@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stubsuper.endDocument();}/** 接收标签结束通知
*/@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// TODO Auto-generated method stubif (localName.equals("item"))list.add(chann);}/** 文档开始通知
*/@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stublist = new ArrayList<channel>();}/** 标签开始通知
*/@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {// TODO Auto-generated method stubchann = 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;}
}

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();}

从第二部分代码,可以看出使用SAX解析XML的步骤:

1、实例化一个工厂SAXParserFactory

2、实例化SAXPraser对象,创建XMLReader 解析器

3、实例化handler,处理器

4、解析器注册一个事件

4、读取文件流

5、解析文件

二、使用pull方式解析

  在android系统中,很多资源文件中,很多都是xml格式,在android系统中解析这些xml的方式,是使用pul解析器进行解析的,它和sax解析一样(个人感觉要比sax简单点),也是采用事件驱动进行解析的,当pull解析器,开始解析之后,我们可以调用它的next()方法,来获取下一个解析事件(就是开始文档,结束文档,开始标签,结束标签),当处于某个元素时可以调用XmlPullParser的getAttributte()方法来获取属性的值,也可调用它的nextText()获取本节点的值。

其实以上描述,就是对整个解析步骤的一个描述,看看代码吧

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() != XmlResourceParser.END_DOCUMENT) {// 如果遇到了开始标签if (xrp.getEventType() == XmlResourceParser.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.getAttributeValue(1);// 通过属性索引来获取属性值map.put("url", url);map.put("name", xrp.nextText());list.add(map);}}xrp.next();// 获取解析下一个事件}} catch (XmlPullParserException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return list;}

三、使用Dom方式解析

基础知识:

     最后来看看Dom解析方式,这种方式解析自己之前也没有用过(在j2ee开发中比较常见,没有做过这方面的东西),在Dom解析的过程中,是先把dom全部文件读入到内存中,然后使用dom的api遍历所有数据,检索想要的数据,这种方式显然是一种比较消耗内存的方式,对于像手机这样的移动设备来讲,内存是非常有限的,所以对于比较大的XML文件,不推荐使用这种方式,但是Dom也有它的优点,它比较直观,在一些方面比SAX方式比较简单。在xml文档比较小的情况下也可以考虑使用dom方式。

Dom方式解析的核心代码如下:

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 blocke.printStackTrace();} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return list;}

总结一下Dom解析的步骤(和sax类似)

1、调用 DocumentBuilderFactory.newInstance() 方法得到 DOM 解析器工厂类实例。

2、调用解析器工厂实例类的 newDocumentBuilder() 方法得到 DOM 解析器对象

3、调用 DOM 解析器对象的 parse() 方法解析 XML 文档得到代表整个文档的 Document 对象。

四、总结

       除以上三种外还有很多解析xml的方法,比如DOM4J、JDOM等等。但其基本的解析方式包含两种,一种是事件驱动的(代表SAX),另一种方式是基于文档结构(代表DOM)。其他的只不过语法不一样而已。




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/295612.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博士毕业的人也会交“智商税”?现实远比我们想象的残酷……

全世界只有3.14 % 的人关注了爆炸吧知识2018 年的那个多事之秋&#xff0c;我终于在人生快要过半的时候拿到了博士学位。大毛和小鱼是我博士期间玩得最好的兄弟&#xff0c;我们三人水平差不多&#xff0c;志向差不多&#xff0c;博士毕业后都进了双非高校。现实不像是想象中那…

UVA-1045 - The Great Wall Game(二分图最佳匹配)

题意:在一个n*n的棋盘上有n个棋子&#xff0c;要求通过移动棋子使棋子的排布满足以下情况之一&#xff1a;呈横行排列&#xff1b;呈纵行排列&#xff1b;呈对角线排列(有两条)。 棋子移动一个单元格的费用为1&#xff0c;总费用为所有棋子的移动费用之和。求最小费用。 分析:因…

聊一聊声明式接口调用与Nacos的结合使用

背景 对于公司内部的 API 接口&#xff0c;在引入注册中心之后&#xff0c;免不了会用上服务发现这个东西。现在比较流行的接口调用方式应该是基于声明式接口的调用&#xff0c;它使得开发变得更加简化和快捷。.NET 在声明式接口调用这一块&#xff0c;有 WebApiClient 和 Refi…

三次握手和四次挥手图解_三次握手和四次挥手简单理解

TCP三次握手TCP标志位TCP在其协议头中使用大量的标志位或者说1位&#xff08;bit&#xff09;布尔域来控制连接状态&#xff0c;一个包中有可以设置多个标志位。TCP是主机对主机层的传输控制协议&#xff0c;提供可靠的连接服务&#xff0c;采用三次握手确认建立一个连接&#…

分布式搜索ElasticSearch单机与服务器环境搭建

先到http://www.elasticsearch.org/download/下载最新版的elasticsearch运行包&#xff0c;本文写时最新的是0.19.1&#xff0c;作者是个很勤快的人&#xff0c;es的更新很频繁&#xff0c;bug修复得很快。下载完解开有三个包:bin是运行的脚本&#xff0c;config是设置文件&…

Android之基于BaseAdapter和SimpleAdapter的GridView

GridView 第一种方式:用SimpleAdapter 先来贴出本文代码运行的结果: 本文需要添加/修改3个文件:main.xml、night_item.xml、JAVA源代码。 main.xml源代码如下,本身是个GirdView,用于装载Item: <?xml version="1.0" encoding="utf-8"?> <…

IOS开发CAKeyframeAnimation的基本使用与keypath的列举

2019独角兽企业重金招聘Python工程师标准>>> CAKeyframeAnimation跟CABasicAnimation的区别是&#xff1a;CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue)&#xff0c;而CAKeyframeAnimation会使用一个NSArray保存这些数值 - (void)value {CAKe…

少女为什么会身上香香的?

1 一旦接受这个设定苏打窃瓦辛格&#xff08;via.煎甜担担面&#xff09;▼2 有被冒犯到▼3 哈哈哈哈哈▼4 就差了难忘今宵▼5 还是挺在理的▼6 欣慰中带着点点悲伤▼7 原来是你的错▼8 哈哈哈哈哈▼你点的每个赞&#xff0c;我都认真当成了喜欢

Android之Android Studio三种方式导入外部资源 以及 报错处理

Android Studio三种方式导入外部资源 以及 报错处理 android studio提供了三种方式导入外部资源: 1. Library dependency – 在线添加、需联网下载 、 2. File dependency – 从本地添加一些jar包(要先将jar包</

linux系统服务设置命令--chkconfig命令参数及用法详解

chkconfig(check config) 功能说明&#xff1a;chkconfig命令主要用来更新&#xff08;启动或停止&#xff09;和查询系统服务的运行级信息。谨记chkconfig不是立即自动禁止或激活一个服务&#xff0c;它只是简单的改变了符号连接。 语  法&#xff1a;chkconfig [--add][--…

android飞翔的小鸟游戏素材包_开心消消乐×愤怒的小鸟:为开心而战

手机里总有那么一些游戏&#xff0c;是你一旦不小心打开&#xff0c;就完全停不下来的。在这份“一直玩一直爽游戏清单”里&#xff0c;绝对少不了开心消消乐和愤怒的小鸟的身影。神奇的是&#xff0c;在2020的夏天&#xff0c;它们合体了&#xff01;在接到开心消消乐的brief时…

查看Nginx,Apache,lighttpd,Mysql,Php的编译参数

查看一些常见服务的在编译安装时的参数&#xff1a; 1.Nginx 编译安装时的参数 [roottest ~]# /usr/local/nginx/sbin/nginx -V nginx version: nginx/0.7.65 built by gcc 4.1.2 20080704 (Red Hat 4.1.2-48) TLS SNI support disabled configure arguments: --userwww --grou…

使用原生js写ajax

// 使用原生js 封装ajax // 兼容xhr对象 function createXHR(){if(typeof XMLHttpRequest ! "undefined"){ // 非IE6浏览器return new XMLHttpRequest();}else if(typeof ActiveXObject ! "undefined"){ // IE6浏览器var version ["MSXML2.XMLHttp…

RabbitMQ 处理过慢,原来是一个 SQL 缓存框架导致的 GC 频繁触发

一&#xff1a;背景 1. 讲故事上个月底&#xff0c;有位朋友微信找到我&#xff0c;说他的程序 多线程处理 RabbitMQ 时过慢&#xff0c;帮忙分析下什么原因&#xff0c;截图如下&#xff1a;这问题抛出来&#xff0c;有点懵逼&#xff0c;没说CPU爆高&#xff0c;也没说内存泄…

3部世界顶级宇宙纪录片,献给对宇宙万物充满好奇的你~

全世界只有3.14 % 的人关注了爆炸吧知识宇宙深邃美丽&#xff0c;是黑夜的荧光&#xff0c;是夏天里冒着凉气的西瓜&#xff0c;总是诱人地勾起一代又一代人探索的欲望。对于宇宙思索与探索&#xff0c;人类的脚步从未停止。正是人类对宇宙的好奇&#xff0c;撑起了人类发展的大…

二元函数偏导数公式_偏导数计算公式大全

如果函数f(x)在(a,b)中每一点处都可导,则称f(x)在(a,b)上可导,则可建立f(x)的导函数,简称导数。以下是小学生作文网小编给大家提供的导数公式大全,快来看看吧!导数的定义:当自变量的增量... 2018-12-29 阅读全文 >> 导数公式大全-偏导数基本公式大全_营销/活动策划_计…

在.net 4.0程序中使用TPL Dataflow

今天写了一个小程序&#xff0c;用到了TPL Dataflow&#xff0c;结果在部署的时候发现了一个问题&#xff1a;客户的服务器中有win2003的机器&#xff0c;2003是不支持.net 4.5的&#xff0c;但TPL Dataflow却只能在.net 4.5的程序上使用。 在网上搜了一下&#xff0c;MSDN论坛…

Android之平时遇见的异常和错误总结(不断更新)

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程 安卓错误经验累积 1、当出现下面错误时候 08-21 03:43:16.679: E/AndroidRuntime(1087): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.…

【20120517】【早晨】

今天早上没去GIS程序设计的实验&#xff0c;窝在寝室准备看图论和汇编。。。不多说了&#xff0c;现在开始~~

OC类

2019独角兽企业重金招聘Python工程师标准>>> OC语言的一个类分为两个文件一个.h&#xff0c;一个.m&#xff0c;.h为头文件用来添加实例变量和方法声明。.m文件里面写入方法的实现 .h一般如下 interface 类名:父类 属性声明 方法声明 end .m一般如下 implementation…