本文出自:http://blog.csdn.net/ichliebephone/article/details/5965826
一.
简单介绍
XML(
eX
tensibleMarkupLanguage) ,
即可扩展标记语言
, 是一种简单的数据存储语言,使用一系列简单的标记描述数据
。
XML经常用作
Internet 上的一种数据格式 ,因此
如果您希望通过Internet
访问数据,则数据很有可能是
XML 格式 ,或者
如果您希望发送数据给Web
服务,那么您可能也需要发送
XML 。简而言之,如果您的
Android 应用程序将利用
Internet ,那么您可能需要使用
XML 。幸运的是,您可以采用多种方法在
Android 上使用
XML 。这个学习系列就和大家一起学习一下在
Android平台上读写
XML
数据的多种方式。
而最近用业余时间做了一个《地震及时通》,其中就需要从网络上读取实时的XML
形式的地震数据,因此我们在学习的同时将会完成读取
XML 形式的地震数据的
Demo 例子。
二.
基础知识
2.1整体介绍
Android上对
XML
解析的支持是相当强大的,我们可以先来看一下 Android
中和
XML 解析相关的包:
1.
a
ndroid.sax
这是
Android SDK
提供的sax
解析的包,因为可以对具体的
Element 设置监听进行处理,因此有更好鲁棒性。
2.
a
ndroid.util .Xml
这是
a ndroid.util
包中的其中一个类,提供
XML相关的实用方法,而且都是
publicstatic 形式的类方法,即可以直接以类名调用。
3.
javax.xml.parsers
这是使用原来Java
SDK
用于xml
处理的 API
,即 JAXP( JavaAPIforXMLProcessing
),主要提供了
SAX
和 DOM
方式解析 XML
的工厂方法。
4.
org.w3c.dom
提供具体的和DOM
方式解析
XML 相关的接口,如
Document 、
Element 等。
5.
org.xml.sax
提供具体的和SAX
方式解析
XML 相关的接口,如
XMLReader 及
4 个处理用的
Handler 等。
6.
org.xml.sax.helpers
提供SAX
的帮助类,以便更方便的用来解析,比如实现了
SAX 的
4 个处理用的
Handler 接口的
DefaultHandler ,用来更方便使用
XML 过滤器
XMLFilter 的 XMLFilterImpl
,和用于更方便创建
XMLReader的 XMLReaderFactory
等。
7.
org.xmlpull.v1
提供Pull
方式解析
XML 的接口
XmlPullParser 和用于写
XML 的
XmlSerializer 等。
以上就是Android
提供的和
XML 读写相关的一些包,在这个学习系列中我们将对这些包的功能进行具体的介绍,并依次使用这些
SAX
解析的方式完成读取 XML
地震数据的 Demo
例子。
2.2SAX方式介绍
SAX
( SimpleAPIforXML
)
是 基于
事件驱动的XML
处理 模式,
主要是围绕着事件源以及事件处理器(或者叫监听器)来工作的。一个可以产生事件的对象被称为事件源,而可以针对事件产生响应的对象就被叫做事件处理器。事件源和事件处理器是通过在事件源中的事件处理器注册方法连接的。这样当事件源产生事件后
(比如碰到
XML元素的开始和结束等 )
,调用事件处理器
(由许多回调函数组成)
相应的处理方法,一个事件就获得了处理。当然在事件源调用事件处理器中特定方法的时候,会传递给事件处理器相应事件的状态信息
(即回调函数中的参数)
,这样事件处理器才能够根据事件信息来决定自己的行为。
其中常用的事件处理回调函数有用于文档处理的文档开始:
startDocument()
,文档结束:
endDocument
()
,
XML元素开始: startElement(Stringuri,StringlocalName,StringqName,
Attributesattributes)
,
XML元素内容: characters(
char
[]ch,
int
start,
int
length)
,
XML元素结束: endElement(Stringuri,StringlocalName,StringqName)
,还有解析错误的回调函数 error
(
SAXParseException
exception)
等。
在Android
系统中,提供了两种
SAX 解析的包,一种是原来
Java SDK
就有的用于XML
处理的 API
(称为 JAXP:
JavaAPIforXMLProcessing
,包含了
SAX和
DOM 两者相关的
API ),相关内容在包
javax.xml.parsers
中。还有一种是经过了 Android
SDK
包装了之后的sax
包,相关内容在包 android.sax
中。
这部分我们先来学习原来JavaSDK就有的用SAX方式处理XML的相关方法。在javax.xml.parsers包中,和SAX相关的为两个类:SAX解析器工厂SAXParserFactory和SAX解析器SAXParser。SAXParserFactory有set方法和get方法可以设置和获取一些配置选项,其中最重要的是调用newSAXParser()创建解析器SAXParser类的实例。SAXParser类包装了底层的SAX解析器(org.xml.sax.XMLReader的实例),即SAXParser实例调用parse方法进行XML解析时,实际上会调用底层具体的org.xml.sax包中的XMLReader。SAXParser实例也可以通过调用getXMLReader()方法获得底层的XMLReader实例,一旦获得该实例,就可以按XMLReader方式使用更一般和具体的SAX方法。
通过以上的介绍我们知道org.xml.sax包是底层具体的负责SAX解析相关的内容,并且为上层javax.xml.parsers包提供SAX解析器等相关调用。下面我们就具体介绍一下用SAX进行解析的步骤。
在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parse()方法来开始解析XML文档并根据文档内容产生事件。而事件处理器则是org.xml.sax包中的ContentHandler,DTDHandler,ErrorHandler,以及EntityResolver这四个接口。它们分别处理事件源在解析过程中产生的不同种类的事件(其中主要的为ContentHandler,处理和文档内容相关的事件)。而事件源XMLReader和这四个事件处理器的连接是通过在XMLReader中的相应的事件处理器注册方法set***()来完成的。
因此概况一下具体步骤为:
1.实现一个或多个处理器接口(ContentHandler,ErrorHandler,DTDHandler,orEntityResover)
2.创建一个XMLReader类的实例
3.在新的XMLReader实例中通过大量的set*****()方法注册一个事件处理器的实例
4.调用XMLReader的parse()方法来处理文档启动解析
以上部分的介绍是指使用org.xml.sax包中提供的SAX解析的相关接口时的用法,但是一般常用并且比较方便的为使用javax.xml.parsers包提供的SAX工厂类SAXParserFactory创建SAXParser实例,并且创建一个继承org.xml.sax.helpers包中的DefaultHandler的类,用于实现具体的SAX事件的处理逻辑,DefaultHandler类提供了SAX中ContentHandler,DTDHandler,ErrorHandler,以及EntityResolver这四个接口的所有回调方法默认的空实现,因此我们继承这个类后可以只覆盖我们需要的回调函数即可。然后调用SAXParser实例的parse方法进行解析,用来解析的xml数据的形式可以为InputStreams,Files,URLs,andSAXInputSources等四种形式。
实现步骤和上面类似:
1.在继承DefaultHandler的类里面重写需要的回调函数
2.创建SAXParser实例
3.SAXParser实例调用parse方法启动解析
下面我们就用上面介绍的JavaSDK中的SAX方式来实现解析XML形式的地震数据的Demo例子。
三.实例开发
我们要解析的为美国地质调查局USGS提供的地震数据,xml数据地址为:
http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml
http://earthquake.usgs.gov/earthquakes/catalogs/7day-M2.5.xml
http://earthquake.usgs.gov/earthquakes/catalogs/7day-M5.xml
分别为1天以内2.5级以上、7天内2.5级以上和7天内5级以上地震数据。
Xml数据的格式如下所示:
- <?xmlversion="1.0"?>
- <feedxmlns="http://www.w3.org/2005/Atom"xmlns:georss="http://www.georss.org/georss">
- <updated>2010-09-15T04:41:18Z</updated>
- <title>USGSM2.5+Earthquakes</title>
- <subtitle>Real-time,worldwideearthquakelistforthepastday</subtitle>
- <linkrel="self"href="http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml"mce_href="http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml"/>
- <linkhref="http://earthquake.usgs.gov/earthquakes/"mce_href="http://earthquake.usgs.gov/earthquakes/"/>
- <author><name>U.S.GeologicalSurvey</name></author>
- <id>http://earthquake.usgs.gov/</id>
- <icon>/favicon.ico</icon>
- <entry>
- <id>urn:earthquake-usgs-gov:ak:10078833</id>
- <title>M2.9,SouthernAlaska</title>
- <updated>2010-09-15T04:14:03Z</updated>
- <linkrel="alternate"type="text/html"href="http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/ak10078833.php"mce_href="http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/ak10078833.php"/>
- <summarytype="html">
- </summary>
- <georss:point>59.9094-153.1241</georss:point>
- <georss:elev>-98900</georss:elev>
- <categorylabel="Age"term="Pasthour"/>
- </entry>
- <entry>
- </entry>
- </feed>
下面我们就来完成用JavaSAX的方式解析以上XML形式的USGS地震数据的Android例子。
我们要完成的效果图如下图1所示:
图1ListView列表显示的地震数据
解析完地震数据后用ListView列表的方式显示每条地震的震级和地名信息。
新建一个Android工程AndroidXMLDemoSax。
首先新建添加一个类EarthquakeEntry,用来保存一条地震信息,类的内容为:
- publicclassEarthquakeEntry{
- privateDatedate;
- privateLocationlocation;
- privateStringplace;
- privateStringlink;
- privatedoublemagnitude;
- privatedoubleelev;
- publicEarthquakeEntry()
- {
- }
- publicEarthquakeEntry(Date_date,String_place,String_link,Location_location,double_magnitude,double_elev)
- {
- this.date=_date;
- this.location=_location;
- this.place=_place;
- this.link=_link;
- this.magnitude=_magnitude;
- this.elev=_elev;
- }
- publicvoidsetDate(Date_date)
- {
- this.date=_date;
- }
- publicvoidsetLocation(Location_location)
- {
- this.location=_location;
- }
- publicvoidsetPlace(String_place)
- {
- this.place=_place;
- }
- publicvoidsetLink(String_link)
- {
- this.link=_link;
- }
- publicvoidsetMagnitude(double_magnitude)
- {
- this.magnitude=_magnitude;
- }
- publicvoidsetElev(double_elev)
- {
- this.elev=_elev;
- }
- publicDategetDate()
- {
- returnthis.date;
- }
- publicLocationgetLocation()
- {
- returnthis.location;
- }
- publicStringgetPlace()
- {
- returnthis.place;
- }
- publicStringgetLink()
- {
- returnthis.link;
- }
- publicdoublegetMagnitude()
- {
- returnthis.magnitude;
- }
- publicdoublegetElev()
- {
- returnthis.elev;
- }
- @Override
- publicStringtoString(){
- StringearthquakeString="M"+magnitude+""+place;
- returnearthquakeString;
- }
- }
比较简单,定义和一条地震内容对应的变量,并设置set和get函数,并且重写toString()函数在ListView输出时用。
接着新建添加一个类SaxEarthquakeHandler,继承DefaultHandler,完成解析地震数据的具体逻辑实现,内容如下:
- publicclassSaxEarthquakeHandlerextendsDefaultHandler{
- privateStringkEntryElementName="entry";
- privateStringkLinkElementName="link";
- privateStringkTitleElementName="title";
- privateStringkUpdatedElementName="updated";
- privateStringkGeoRSSPointElementName="point";
- privateStringkGeoRSSElevElementName="elev";
- privateArrayList<EarthquakeEntry>earthquakeEntryList;
- privateEarthquakeEntryearthquakeEntry;
- privateStringBuildercurrentDataBuilder;
- privateBooleanstartEntryElementFlag=false;
- publicArrayList<EarthquakeEntry>getEarthquakeEntryList()
- {
- returnthis.earthquakeEntryList;
- }
- @Override
- publicvoidstartDocument()throwsSAXException{
- super.startDocument();
- earthquakeEntryList=newArrayList<EarthquakeEntry>();
- currentDataBuilder=newStringBuilder();
- }
- @Override
- publicvoidendDocument()throwsSAXException{
- Log.v("Sax","End");
- }
- @Override
- publicvoidstartElement(Stringuri,StringlocalName,StringqName,
- Attributesattributes)throwsSAXException{
- super.startElement(uri,localName,qName,attributes);
- if(localName.equalsIgnoreCase(kEntryElementName))
- {
- earthquakeEntry=newEarthquakeEntry();
- startEntryElementFlag=true;
- }
- elseif((localName.equalsIgnoreCase(kLinkElementName))&&(startEntryElementFlag==true)){
- StringrelAttribute=attributes.getValue("rel");
- if(relAttribute.equalsIgnoreCase("alternate"))
- {
- StringwebLink=attributes.getValue("href");
- earthquakeEntry.setLink(webLink);
- }
- }
- }
- @Override
- publicvoidcharacters(char[]ch,intstart,intlength)
- throwsSAXException{
- super.characters(ch,start,length);
- currentDataBuilder.append(ch,start,length);
- }
- @Override
- publicvoidendElement(Stringuri,StringlocalName,StringqName)
- throwsSAXException{
- super.endElement(uri,localName,qName);
- if(startEntryElementFlag==true)
- {
- StringcurrentData=currentDataBuilder.toString();
- if(localName.equalsIgnoreCase(kTitleElementName)){
- StringmagnitudeString=currentData.split("")[1];
- intend=magnitudeString.length()-1;
- magnitudeString=magnitudeString.substring(0,end);
- doublemagnitude=Double.parseDouble(magnitudeString);
- earthquakeEntry.setMagnitude(magnitude);
- Stringplace=currentData.split(",")[1].trim();
- earthquakeEntry.setPlace(place);
- }
- elseif(localName.equalsIgnoreCase(kUpdatedElementName)){
- SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
- Dateqdate=newGregorianCalendar(0,0,0).getTime();
- try{
- qdate=sdf.parse(currentData);
- }catch(ParseExceptione){
- e.printStackTrace();
- }
- earthquakeEntry.setDate(qdate);
- }
- elseif(localName.equalsIgnoreCase(kGeoRSSPointElementName)){
- String[]latLongitude=currentData.split("");
- Locationlocation=newLocation("dummyGPS");
- location.setLatitude(Double.parseDouble(latLongitude[0]));
- location.setLongitude(Double.parseDouble(latLongitude[1]));
- earthquakeEntry.setLocation(location);
- }
- elseif(localName.equalsIgnoreCase(kGeoRSSElevElementName)){
- doubleevel;
- try{
- evel=Double.parseDouble(currentData);
- }catch(Exceptione){
- e.printStackTrace();
- evel=0;
- }
- Log.v("Sax_Elev",String.valueOf(evel));
- earthquakeEntry.setElev(evel);
- }
- elseif(localName.equalsIgnoreCase(kEntryElementName))
- {
- earthquakeEntryList.add(earthquakeEntry);
- startEntryElementFlag=false;
- }
- currentDataBuilder.setLength(0);
- }
- }
- }
首先定义了xml解析和保存解析结果等相关的一些变量,接着定义一个get函数
//获取解析的地震列表
publicArrayList<EarthquakeEntry>getEarthquakeEntryList()
{
returnthis.earthquakeEntryList;
}
返回解析的地震列表数据。
然后就是具体的xml解析回调函数的重写实现,因为继承了类DefaultHandler,包含了SAX处理相关的4个Handler的所有回调函数的空实现,因此我们只需覆盖我们需要的回调函数。这是我们只重写了和文档内容处理相关的ContentHandler中startDocument,endDocument,startElement,characters,和endElement这几个回调函数,在实际应用中你可能还需添加错误处理或者其他的回调函数,只需重写覆盖即可。
回调函数中具体的处理逻辑和你的XML数据的内容有关,以上实现了解析USGS的地震数据的处理逻辑,并添加了注释,如果有兴趣你可以对照着USGS的XML数据格式来看,这就不具体的讲了。
和地震相关的存储类和SAX处理回调函数都完成了,接下来我们就来调用SaxEarthquakeHandler开始解析并显示数据。
先修改res/layout下的main.xml为:
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <ListView
- android:id="@+id/list"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- />
- </LinearLayout>
添加了一个用于显示的ListView控件。
接着添加AndroidXMLDemoSax.java文件的内容。
先添加获取xml数据源的方法:
- privateInputStreamreadEarthquakeDataFromInternet()
- {
- URLinfoUrl=null;
- InputStreaminStream=null;
- try{
- infoUrl=newURL("http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml");
- URLConnectionconnection=infoUrl.openConnection();
- HttpURLConnectionhttpConnection=(HttpURLConnection)connection;
- intresponseCode=httpConnection.getResponseCode();
- if(responseCode==HttpURLConnection.HTTP_OK)
- {
- inStream=httpConnection.getInputStream();
- }
- }catch(MalformedURLExceptione){
- e.printStackTrace();
- }catch(IOExceptione){
- e.printStackTrace();
- }
- returninStream;
- }
这是从USGS的网站上读取XML数据并以InputStream的形式返回。因为需要用到联网功能,所以还得在manifest.xml文件中添加联网权限:
<uses-permissionandroid:name="android.permission.INTERNET"/>
这是联网获取XML数据,也可以从本地读取XML数据,因为校园网会打不开USGS的网站,因此复制了一份USGS的地震数据以文件的形式保存在assets文件夹下,并使用如下函数读取:
- privateInputStreamreadEarthquakeDataFromFile()
- {
- InputStreaminStream=null;
- try{
- inStream=this.getAssets().open("USGS_Earthquake_1M2_5.xml");
- }catch(IOExceptione){
- e.printStackTrace();
- }
- returninStream;
- }
有了XML数据,就可以接下来进行解析了。
- InputStreamearthquakeStream=readEarthquakeDataFromFile();
- SAXParserFactoryfactory=SAXParserFactory.newInstance();
- try{
- SAXParserparser=factory.newSAXParser();
- SaxEarthquakeHandlersaxHandler=newSaxEarthquakeHandler();
- parser.parse(earthquakeStream,saxHandler);
- earthquakeEntryList=saxHandler.getEarthquakeEntryList();
- }catch(Exceptione){
- e.printStackTrace();
- }
最后添加定义相关变量,用把解析的数据用ListView显示:
- ListViewlist;
- ArrayAdapter<EarthquakeEntry>adapter;
- ArrayList<EarthquakeEntry>earthquakeEntryList;
- list=(ListView)this.findViewById(R.id.list);
- adapter=newArrayAdapter<EarthquakeEntry>(this,android.R.layout.simple_list_item_1,earthquakeEntryList);
- list.setAdapter(adapter);
完成了,可以保存运行看下效果。
以上使用的是javax.xml.parsers包中的SAXParser来实现,SAXParser包装了底层的XMLReader,实现起来更加方便。但是我们也可以使用XMLReader来实现解析,下面就看下使用具体的XMLReader的方式,实现代码如下所示:
- XMLReaderxmlReader=null;
- try{
- System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");
- xmlReader=XMLReaderFactory.createXMLReader();
- }catch(SAXExceptione){
- e.printStackTrace();
- }
- SaxEarthquakeHandlersaxHandler=newSaxEarthquakeHandler();
- xmlReader.setContentHandler(saxHandler);
- InputSourceinSource=newInputSource(earthquakeStream);
- try{
- xmlReader.parse(inSource);
- }catch(Exceptione){
- e.printStackTrace();
- }
- earthquakeEntryList=saxHandler.getEarthquakeEntryList();
其中获取XMLReader的方式有两种,一种是先获取SAXParser,然后通过getXMLReader()方法来获取,
xmlReader=SAXParserFactory.newInstance().newSAXParser().getXMLReader();
另一种是直接使用XMLReader的工厂类XMLReaderFactory调用createXMLReader()方法创建,
xmlReader=XMLReaderFactory.createXMLReader();
但不管是那种方式,只有获得了XMLReader实例,接下来的操作都是一样的,先注册文档内容的事件处理器实例,
xmlReader.setContentHandler(saxHandler);
然后调用parse方法开始解析,
xmlReader.parse(inSource);
这样就用XMLReader进行了XML解析。
四.总结
在这部分中我们首先学习了Android上和XML解析相关的各个包的简单介绍,并且从有这么多个相关的包我们可以知道Android为XML的读写提供了相当大的支持。
然后具体学习了Android上使用SAX方式解析XML的基本知识,使用javax.xml.parsers包中的SAXParser进行解析,及使用org.xml.sax包中的XMLReader进行解析两种方式分别的步骤,最后用解析USGS地震数据的Demo例子来实现介绍的内容。
这部分介绍的SAX方式是属于原来Java就有的XML处理方式,同时,Android平台为了使解析XML还能更加方便和更加健壮,提供了android.sax包来进行SAX进行XML,这部分内容我们以后我们继续接着学习。
注:
参考资料:http://www.ibm.com/developerworks/cn/xml/x-saxhandle/
分享到:
相关推荐
NULL 博文链接:https://andy2019.iteye.com/blog/2148057
Android XML解析之SAX解析 简单方便的解析方法
这是一个完整的eclipse项目,打开后就可以看代码~
在Android中,常见的XML解析器分别为SAX解析器、DOM解析器和PULL解析器. 这里的源代码介绍的是Android XML解析之SAX方式
Android 创建与解析XML Sax方式
学习xml——sax解析的项目小示例 非常简单易懂 而且包括多种sax解析的方法 如xmlReader,saxBuilder工厂,还包括一个dom解析的示例(DocumentBuilder工厂)
一个项目同时用dom解析和sax解析xml文件貌似会报错,项目框架建一直是用sax和dom4j解析xml文件的。当我用dom解析xml文件。导入包后就报错识别不了xml文件的编码格式。于是做了一个sax解析xml文件的实例
android xml 解析 生成xml sax pull dom
提供了android中使用dom、pull、sax三种方式进行xml解析,xml文件放置在assets文件夹下,view绑定使用butterknife
android解析XML总结(SAX、Pull、Dom三种方式),代码实现
Android XML解析 SAX DOM Pull 以person类为例进行解析,适合初学者学习
android xml解析,sax pull dom三个解析
NULL 博文链接:https://byandby.iteye.com/blog/836754
android解析XML使用SAX方法,文件样例。路径为SDCARD里的XML。当然也可以通过网络来下载XML再进行解析
android 以SAX方式解析xml
SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。 SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符...
XML解析之SAX解析DEMO,之前在播控上有介绍,但是代码排版太乱了,这个就是Android4.0网络编程中的SAX解析例子。
Android中解析xml的三种方式DOM SAX PULL,以及各自优缺点
java学习笔记——使用DOM解析XML和使用SAX解析XML
在JAVA中有两种常见的XML解析方式,DOM和SAX,DOM在解析的时候会将所有的数据一次性载入内存中进行解析,在数据量比较大的情况下,效率非常低.尤其在手机这种对内存和性能要求比较苛刻的设备里面这种方法并不可取. ...