Android XML文档解析(一)——SAX解析
------------------------------------------------------------------------------------------------------
此文章仅作为学习交流所用
转载或引用请务必注明原文地址:
http://blog.csdn.net/luzhenrong45/article/details/11851607
或联系作者:luzhenrong45@gmail.com
谢谢!
------------------------------------------------------------------------------------------------------
一. XML介绍
XML:extensible markup language,可扩展标记语言. 与HTML(超文本标记语言,即Hypertext Markup Language)一样,XML也是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML与HTML的设计区别是:XML 被设计为传输和存储数据,其焦点是数据的内容。而HTML 被设计用来显示数据,其焦点是数据的外观。HTML 旨在显示信息,而 XML 旨在传输信息。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。其目的是为了促进Internet上结构化文档的交换。简单的说,XML是一组规则和准则的集合,用于以无格式文本来描述结构化数据.
XML是纯数据描述,与编程语言、操作系统或传输协议无关,从而将数据从以代码为中心的基础结构所产生的约束中解放出来,让数据能够在Web上更自由的流通。然而XML本身只是以纯文本对数据进行编码的一种格式,要想利用XML,或者说利用XML文件中所编码的数据,必须先将数据从纯文本中解析出来,因此,必须有一个能够识别XML文档中信息的解析器,用来解释XML文档并提取其中的数据。根据数据提取的不同需求,又存在着多种解析方式,不同的解析方式有着各自的优缺点和适用环境。选择合适的XML解析技术能够有效提升应用系统的整体性能.在Android中,常见的XML解析器分别为SAX解析器、DOM解析器和PULL解析器.
下面,介绍SAX解析方式.
二. SAX解析
SAX,全称Simple API for XML,既是指一种接口,也是指一个软件包。SAX解析XML文件采用事件驱动的方式进行,也就是说,SAX是逐行扫描文件,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时回调你写好的事件处理程序,然后继续同样的扫描,直至文档结束。使用SAX的优势在于其解析速度较快,占用内存较少(相对于DOM而言)。而且SAX在解析文件的过程中得到自己需要的信息后可以随时终止解析,并不一定要等文件全部解析完毕。凡事有利必有弊,其劣势在于SAX采用的是流式处理方式,当遇到某个标签的时候,它并不会记录下以前所遇到的标签,也就是说,在处理某个标签的时候,比如在 startElement方法中,所能够得到的信息就是标签的名字和属性,至于标签内部的嵌套结构,上层标签、下层标签以及其兄弟节点的名称等等与其结构相关的信息都是不得而知的。实际上就是把XML文件的结构信息丢掉了,如果需要得到这些信息的话,只能你自己在程序里进行处理了。所以相对DOM而言,SAX处理XML文档没有DOM方便,SAX处理的过程相对DOM而言也比较复杂。
- //用于处理文档解析开始事件
- public void startDocument()throws SAXException
- //处理元素开始事件,从参数中可以获得元素所在名称空间的uri,元素名称,属性类表等信息
- public void startElement(String namespacesURI , String localName , String qName , Attributes atts) throws SAXException
- //处理元素结束事件,从参数中可以获得元素所在名称空间的uri,元素名称等信息
- public void endElement(String namespacesURI , String localName , String qName) throws SAXException
- //处理元素的字符内容,从参数中可以获得内容
- public void characters(char[] ch , int start , int length) throws SAXException
- //当文档结束的时候,调用这个方法,可以在其中做一些善后的工作
- public void endDocument() throws SAXException
三. SAX解析XML步骤
Android 使用SAX解析XML文件有两种方式,第一是直接使用SAXParser,或者创建一个XMLReader.不管采用哪种方式,前面三个步骤是一样的.
(一)第一步:加载需要解析的文件,将一个xml文档或者资源变成一个java可以处理的InputStream流.比如我的xml文件名是laolu_xml.xml,放在src目录下,可通过类装载器的方式获得文件路径,再获得文件的输入流
- InputStream is= this.getClass().getClassLoader().getResourceAsStream("laolu_xml.xml");
(二)第二步:新建一个工厂类SAXParserFactory
- SAXParserFactory factory = SAXParserFactory.newInstance();
(三)第三步:让工厂类产生一个SAX的解析类SAXParser
- SAXParser saxParser = factory.newSAXParser();
(四)第四步:可以采用XMLReader解析或直接使用SAXParser解析.
(1)采用XMLReader
- 1) 从SAXPsrser中得到一个XMLReader实例
- XMLReader xmlReader = saxParser.getXMLReader();
- 2) 把自己写的handler注册到XMLReader中,一般最重要的就是ContentHandler:
- SAXForHandler handler = new SAXForHandler (); //SAXForHandler为自己写的SAX解析类
- xmlReader.setContentHandler(handler);
- 3) 开始解析XML
- xmlReader.parse(new InputSource(is));
(2)直接使用SAXParser解析
- SAXForHandler handler = new SAXForHandler ();
- saxParser.parse(is,handler);
两种方式都可以对XML文件进行解析,使用的效果是完全一样的.其实SAXParser是JAXP(JAVA API for XML Processing) 对XMLReader的一个封装,只不过,SAXParser能接受更多类型的参数,能方便对不同数据源的XML文档进行解析,使用XMLReader要稍微烦琐一些.
四.SAX解析实例.
(一)下面以一个工程实例来实现SAX对XML文件的解析.新建一个xml文件: laolu_xml.xml,该文件放在工程根目录下面.内容如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <persons>
- <person id="0">
- <name>刘德华</name>
- <sex>男</sex>
- <age>21</age>
- </person>
- <person id="1">
- <name>张漫玉</name>
- <sex>女</sex>
- <age>22</age>
- </person>
- <person id="2">
- <name>张易谋</name>
- <sex>男</sex>
- <age>23</age>
- </person>
- <person id="3">
- <name>周新驰</name>
- <sex>未知</sex>
- <age>24</age>
- </person>
- <person id="4">
- <name>纳兰容若</name>
- <sex>男</sex>
- <age>25</age>
- </person>
- </persons>
(二)先看一下实际效果图,Android对于XML解析,主要有sax,dom,pull三种方式,这里只介绍sax方式.其他两种以后再介绍.
(三)工程源码框架
(1)布局文件:
main_xml.xml
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- android:orientation="vertical"
- tools:context=".XML_ParseActivity" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/hello_world" />
- <Button
- android:id="@+id/sax_btn"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/sax_parse"/>
- <Button
- android:id="@+id/dom_btn"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/dom_parse"
- />
- <Button
- android:id="@+id/pull_btn"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/pull_parse"
- />
- <ListView
- android:id="@+id/listview"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- </ListView>
- </LinearLayout>
listview_xml.xml
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="horizontal" >
- <View
- android:layout_width="0.5px"
- android:layout_height="fill_parent"
- android:background="#B8B8B8"
- android:visibility="visible" />
- <TextView
- android:id="@+id/id"
- android:layout_width="60dip"
- android:layout_height="40dip"
- />
- <View
- android:layout_width="0.5px"
- android:layout_height="fill_parent"
- android:background="#B8B8B8"
- android:visibility="visible" />
- <TextView
- android:id="@+id/name"
- android:layout_width="120dip"
- android:layout_height="40dip"
- />
- <View
- android:layout_width="0.5px"
- android:layout_height="fill_parent"
- android:background="#B8B8B8"
- android:visibility="visible" />
- <TextView
- android:id="@+id/sex"
- android:layout_width="60dip"
- android:layout_height="40dip"
- />
- <View
- android:layout_width="0.5px"
- android:layout_height="fill_parent"
- android:background="#B8B8B8"
- android:visibility="visible" />
- <TextView
- android:id="@+id/age"
- android:layout_width="120dip"
- android:layout_height="40dip"
- />
- </LinearLayout>
(2)这里重写了SimpleAdapter适配器,使用ListView的效果更好看一点.当然,这一点跟今天的主题没关.
MySimpleAdapter.java
- package com.laolu.adapter;
- import java.util.List;
- import java.util.Map;
- import android.content.Context;
- import android.graphics.Color;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.SimpleAdapter;
- public class MySimpleAdapter extends SimpleAdapter
- {
- public MySimpleAdapter(Context context,
- List<? extends Map<String, ?>> data, int resource, String[] from,
- int[] to)
- {
- super(context, data, resource, from, to);
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent)
- {
- View view=null;
- if(convertView!=null)
- {
- view=convertView;
- }else
- {
- view=super.getView(position,convertView,parent);
- }
- int colors[]={Color.GRAY,Color.WHITE};
- view.setBackgroundColor(colors[position%2]); // 每个item之间颜色不同
- return super.getView(position, view, parent);//返回自己的view
- }
- }
(3)自己实现的SAX解析类SAXForHandler,继承DefaultHandler,而DefaultHandler是实现了ContenHandler的接口的.ContentHandler提供了之前所说的相应的事件方法,所以这个类是最重要的.因为这些回调函数都是自己写代码实现的.
SAXForHandler.java
- package com.laolu.parser;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.xml.sax.Attributes;
- import org.xml.sax.SAXException;
- import org.xml.sax.helpers.DefaultHandler;
- import android.util.Log;
- public class SAXForHandler extends DefaultHandler
- {
- private static final String TAG="SAXForHandler";
- private List<Map<String,Object>> persons;
- private Map<String,Object> person;
- private String nowWitch;
- public List<Map<String,Object>> getPersons()
- {
- return persons;
- }
- @Override
- public void startDocument() throws SAXException {
- persons=new ArrayList<Map<String,Object>>();
- Log.i(TAG,"***startDocument()***");
- }
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException
- {
- if("person".equals(localName))
- {
- for(int i=0;i<attributes.getLength();i++)
- {
- Log.i(TAG,"arrtributes: "+attributes.getLocalName(i)+"_attributes_Value"
- +attributes.getValue(i));
- person=new HashMap<String,Object>();
- person.put("id", attributes.getValue(i));
- }
- }
- nowWitch=localName;
- Log.i(TAG, qName+"***startElement()***");
- }
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- String data=new String(ch,start,length).trim();
- if(!"".equals(data.trim()))
- {
- Log.i(TAG, "content: "+data.trim());
- }
- if("name".equals(nowWitch))
- {
- person.put("name", data.trim());
- }else if("age".equals(nowWitch))
- {
- person.put("age", data.trim());
- }else if("sex".equals(nowWitch))
- {
- person.put("sex", data.trim());
- }
- }
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- Log.i(TAG,qName+"***endElement()***");
- if("person".equals(localName))
- {
- persons.add(person);
- person=null;
- }
- nowWitch=null;
- }
- @Override
- public void endDocument() throws SAXException {
- Log.i(TAG, "***endDocument()***");
- }
- }
(4)主Activity,按下按键,ListView显示解析结果.
- package com.laolu.main;
- import java.io.InputStream;
- import java.util.List;
- import java.util.Map;
- import javax.xml.parsers.SAXParser;
- import javax.xml.parsers.SAXParserFactory;
- import com.example.xml.R;
- import com.laolu.adapter.MySimpleAdapter;
- import com.laolu.parser.SAXForHandler;
- import android.os.Bundle;
- import android.app.Activity;
- import android.util.Log;
- import android.view.Menu;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.ListView;
- import android.widget.SimpleAdapter;
- import android.widget.TextView;
- public class XML_ParseActivity extends Activity
- {
- private static final String SAX="SAX_Parse";
- private static final String DOM="DOM_Parse";
- private static final String PULL="Pull_Parse";
- ListView listView;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main_xml);
- listView=(ListView) findViewById(R.id.listview);
- Button saxButton=(Button) findViewById(R.id.sax_btn);
- Button domButton=(Button) findViewById(R.id.dom_btn);
- Button pullButton=(Button) findViewById(R.id.pull_btn);
- saxButton.setOnClickListener(new MyListener());
- domButton.setOnClickListener(new MyListener());
- pullButton.setOnClickListener(new MyListener());
- }
- public class MyListener implements OnClickListener
- {
- @Override
- public void onClick(View v)
- {
- switch (v.getId())
- {
- case R.id.sax_btn:
- try{
- updateListViewBySAX();
- }catch(Exception e)
- {
- Log.i(SAX,"SAX Exception!!!");
- }
- break;
- case R.id.dom_btn:
- break;
- case R.id.pull_btn:
- break;
- }
- }
- }
- public void updateListViewBySAX() throws Exception
- {
- InputStream inputStream = this.getClass().getClassLoader().
- getResourceAsStream("laolu_xml.xml");
- SAXForHandler saxForHandler = new SAXForHandler();
- SAXParserFactory spf = SAXParserFactory.newInstance();
- SAXParser saxParser = spf.newSAXParser();
- saxParser.parse(inputStream, saxForHandler);//采用
- List<Map<String,Object>> persons = saxForHandler.getPersons();
- SimpleAdapter simpleAdapter=new MySimpleAdapter(this, persons, R.layout.listview_xml,
- new String[]{"id","name","sex","age"}, new int[]{R.id.id,R.id.name,R.id.sex,R.id.age});
- listView.setAdapter(simpleAdapter);
- inputStream.close();
- }
- }
Android XML文档解析(一)——SAX解析的更多相关文章
- JavaEE实战——XML文档DOM、SAX、STAX解析方式详解
原 JavaEE实战--XML文档DOM.SAX.STAX解析方式详解 2016年06月22日 23:10:35 李春春_ 阅读数:3445 标签: DOMSAXSTAXJAXPXML Pull 更多 ...
- Java解析XML文档(简单实例)——dom解析xml
一.前言 用Java解析XML文档,最常用的有两种方法:使用基于事件的XML简单API(Simple API for XML)称为SAX和基于树和节点的文档对象模型(Document Object ...
- XML文档的生成和解析操作方法
XML文档和JSon文档同为网络传输中的数据格式,JSon的解析和创建已经在新浪微博的使用中相当熟悉,故仅仅记载XML文档的相关方法. 关于XML文档: 1.一种便于编辑和传输的数据文件格式 2.xm ...
- [Swift通天遁地]七、数据与安全-(1)XML文档的创建和解析
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 程序员带你学习安卓开发-XML文档的创建与解析
这是程序员带你学习安卓开发系列教程.本文章致力于面向对象程序员可以快速学习开发安卓技术. 上篇文章:程序员带你学习安卓开发系列-Android文件存储 因知识连贯性推荐关注头条号:做全栈攻城狮.从头开 ...
- Java高级特性 第14节 解析XML文档(2) - SAX 技术
一.SAX解析XML文档 SAX的全称是Simple APIs for XML,也即XML简单应用程序接口.与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式.当使用S ...
- 四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例)
众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 下面首先给出这四种方法的jar包下载地址 DOM:在现在的Java JDK里都自带了,在xml- ...
- 四种生成和解析XML文档的方法详解
众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 下面首先给出这四种方法的jar包下载地址 DOM:在现在的Java JDK里都自带了,在xml- ...
- 大杂烩 -- 四种生成和解析XML文档的方法详解
基础大杂烩 -- 目录 众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J DOM:在现在的Java JDK里都自带了,在xml-apis.jar包 ...
随机推荐
- Ubuntu 14.04 64位安装Android Studio 和 genymotion (下)
接上一篇,上回书说到,我们可以进android studio的编辑器了.感觉不错.挺好的,先不说genymotion,先看看你的android项目有没有r文件,项目有没有错误? 如果没有问题的话,下面 ...
- Ubuntu 14.04 64位安装Android Studio 和 genymotion (上)
先说下,Ubuntu 上安装Android Studio真是一路坑阿,一路坑阿,加上天 朝 防火墙挡着,折腾了快一天才弄好阿 找了n多教程,md不是抄的就是转的,而且都没说清楚具体咋装阿,一个图一个 ...
- Cplus
1,factorials[i] = i * factorials[i - 1]; #include <iostream>using namespace std; const int ArS ...
- MySQL的数据库引擎的类型
你能用的数据库引擎取决于mysql在安装的时候是如何被编译的.要添加一个新的引擎,就必须重新编译MYSQL.在缺省情况下,MYSQL支持三个引擎:ISAM.MYISAM和HEAP.另外两种类型INNO ...
- (转)iOS keychain API及其封装
一. Keychain API KeyChain中item的结构为: 1.增加keychain Item OSStatus SecItemAdd (CFDictionaryRef attributes ...
- C语言——文件
需要理解的知识点:数据流.缓冲区.文件类型.文件存取方式 C语言可以将相关定义的数据按照内存的原样写入文件,这对于大规模数据来说比较方便,因为文件的尺寸比单纯的ASCII存储要小很多. 一.文件 ...
- oracle group by rollup,decode,grouping,nvl,nvl2,nullif,grouping_id,group_id,grouping sets,RATIO_TO
干oracle 047文章12当问题,经验group by 声明.因此邂逅group by rollup,decode,grouping,nvl,nvl2,nullif,RATIO_TO_REPOR ...
- NUnit单元测试初试
创建项目,创建几个方法 创建测试类 开启NUnit测试工具,新建一个测试项目 打开测试的程序集 选择节点,点击测试,绿色通过,红色说明有错误
- css中常用的标签
最常用的标签 left 左 top 上 right 右 bottom 下 font 字体 size 大小 width 宽度 height 高度 class 类 label 标签 form 表单 gro ...
- Android(性能)
■ 数据传输 对象和字节流之间的转换 为什么要转? 持久化(装逼说法,JVM非运行的场合),他进程(装逼说法,其他机器JVM,不同的JVM) Parcelable和Serializable 初衷: P ...