Android开发之XML文件解析
2011-05-11 10:52
656 查看
xml文件得到了越来越多的应用,我们可以用它来存储程序的配置数据,也可以在网络上以xml文件传递数据集。所以我们需要学习在Android程序中解析xml文件的方法。由于Android的开发环境是Java,所以Android程序中解析xml文件的方法和Java中解析xml文件的方法是一样的。
1、 SAX 编程技术及SAX的处理机制
SAX是Simple API for XML的缩写,其处理机制是建立在流和事件的基础之上,即将XML看作是“流(stream) ”,SAX“读取器”在遇到XML的“构件”(如Element,Text等)时,会产生相应的事件,然后再利用注册在“解析器”上的事件处理器时进行事件处理。在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parse()方法来开始解析XML文档并根据文档内容产生事件。而事件处理器则是org.xml.sax包中的ContentHandler,DTDHandler,ErrorHandler,以及EntityResolver这四个接口。它们分别处理事件源在解析过程中产生的不同种类的事件(其中DTDHandler是为解析文档DTD时而用)。而事件源XMLReader和这四个事件处理器的连接是通过在XMLReader中的相应的事件处理器注册方法set***()来完成的。
xml框架结构图
![](https://oscdn.geek-share.com/Uploads/Images/Content/201912/09/5da0314f7181723870e5eb231ded3e62.gif)
SAX解析并不透明的进行存储及创建任何数据结构,而此类工作完全交给用户实现的事件处理器。
2、 解析器及主要的SAX API说明
(1)SAXParserFactory:
其为SAXParser对象的工厂对象,使应用程序能够配置和获取基于 SAX 的解析器以解析 XML 文档。
获取该类实例的方法:SAXParserFactory.newInstance()
(2)SAXParser(解析器)
利用其包装的XMLReader(包装器)解析来自文件、输入流、URL中的XML,并把解析事件报告给提定的处理器。
* 获取XMLReader方法:
XMLReader reader=SAXParserFactory.newInstance().newSAXParser().getXMLReader();
reader.parse(InputSource input);
(3)DefaultHandler
为了实现ContentHandler接口,不得不把ContentHandler中所有的抽象方法都实现,这样比较麻烦。SAX API已经考虑到这个问题,在它的org.xml.sax.helper包中为我们提供了一个方便实现各种处理器接口的帮助类DefaultHandler。其实现了四个核心 SAX2 处理程器接口中的所有回调(适配器模式),该类需要开发者自行继承,并实现“感兴趣”的方法。
四个核心的SAX2处理器接口为:
EntityResolver
DTDHandler
ContentHandler[H21] (构件)
ErrorHandler
3、 事件处理器中的各个方法定义及功能
void startDocument():在文档开始处的事件处理方法(回调方法)
void endDocument():在文档结束的事件处理方法
void startElement(String uri,String lname,String qname,Attributs attrs(属性处理)):在元素开始处的事件处理方法
void endElement(String uri,String lname,String qname):在元素结束处的事件处理方法
uri:名字空间的URI(如果支持名字空间)
lname:返回元素的限定名,<bean>返回bean,而<util:list>返回list(如果支持名字空间)
qname:带前缀元素名(如果支持名字空间),如<util:list>将返回util:list
attrs:返回该元素全部属性对象
characters(char[] data,int index,int length):当遇到字符数据时的事件处理方法。
data:为XML字符串构成的数组(每次根据缓冲区大小进行传递向后滚动)
index:当前字符串中第一个字符在data中的位置
length:当前字符串长度
4、 SAX 编程方法
4.1、 工作原理:
<bookCase>
<book id="1">
<title>spring in action(中文版)</title>
</book>
</bookCase>
当一个SAXParser遇到以上的XML时,依次会调用:startDocument,startElement,startElement,startElement,characters(如内容很长可能会有若干次),endElement, endElement, endElement,endDocument。
4.2、 实现步骤:
(1)实现继承自DefalutHandler适配器的实现类,覆写“感兴趣”的方法。
(2)获得SAXParserFactory实例。
(3)由SAXParserFactory获得XMLReader实例。
(4)注册处理文档内容解析事件的ContentHandler
(5)调用XMLReader实例的parser方法,此时需给出“XML源”
示例:新建一个Android应用程序,在main.xml中添加一个按钮,当我们点击这个按钮时将会从本地tomcat服务器上下载一个xml文件,将xml文件的内容保存在String对象中。然后用SAX解析这个String对象。
需要说明的是xml源文件中各标签之间如果要有空格、Tap键等格式字符,因为SAX会把空格、Tab键解析成一个空白节点。这样的话可能会使程序不能输出我们想要显示的内容。在ContentHandler中重写处理空格的方法可以解决这个问题。这里为了简单起见,不再重写处理空格等字符的方法。
下载的xml文件:
源代码:
main.xml
Android_xml.java
MyContentHandler.java
HttpDownloader.java
FileUtil.java
AndroidManifest.xml
运行结果:
界面:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201912/09/487a36ca024d6e61a4b71bb42c9a968a.gif)
点击“解析XML文件”按钮打印以下内容:
1、 SAX 编程技术及SAX的处理机制
SAX是Simple API for XML的缩写,其处理机制是建立在流和事件的基础之上,即将XML看作是“流(stream) ”,SAX“读取器”在遇到XML的“构件”(如Element,Text等)时,会产生相应的事件,然后再利用注册在“解析器”上的事件处理器时进行事件处理。在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parse()方法来开始解析XML文档并根据文档内容产生事件。而事件处理器则是org.xml.sax包中的ContentHandler,DTDHandler,ErrorHandler,以及EntityResolver这四个接口。它们分别处理事件源在解析过程中产生的不同种类的事件(其中DTDHandler是为解析文档DTD时而用)。而事件源XMLReader和这四个事件处理器的连接是通过在XMLReader中的相应的事件处理器注册方法set***()来完成的。
xml框架结构图
![](https://oscdn.geek-share.com/Uploads/Images/Content/201912/09/5da0314f7181723870e5eb231ded3e62.gif)
SAX解析并不透明的进行存储及创建任何数据结构,而此类工作完全交给用户实现的事件处理器。
2、 解析器及主要的SAX API说明
(1)SAXParserFactory:
其为SAXParser对象的工厂对象,使应用程序能够配置和获取基于 SAX 的解析器以解析 XML 文档。
获取该类实例的方法:SAXParserFactory.newInstance()
(2)SAXParser(解析器)
利用其包装的XMLReader(包装器)解析来自文件、输入流、URL中的XML,并把解析事件报告给提定的处理器。
* 获取XMLReader方法:
XMLReader reader=SAXParserFactory.newInstance().newSAXParser().getXMLReader();
reader.parse(InputSource input);
(3)DefaultHandler
为了实现ContentHandler接口,不得不把ContentHandler中所有的抽象方法都实现,这样比较麻烦。SAX API已经考虑到这个问题,在它的org.xml.sax.helper包中为我们提供了一个方便实现各种处理器接口的帮助类DefaultHandler。其实现了四个核心 SAX2 处理程器接口中的所有回调(适配器模式),该类需要开发者自行继承,并实现“感兴趣”的方法。
四个核心的SAX2处理器接口为:
EntityResolver
DTDHandler
ContentHandler[H21] (构件)
ErrorHandler
3、 事件处理器中的各个方法定义及功能
void startDocument():在文档开始处的事件处理方法(回调方法)
void endDocument():在文档结束的事件处理方法
void startElement(String uri,String lname,String qname,Attributs attrs(属性处理)):在元素开始处的事件处理方法
void endElement(String uri,String lname,String qname):在元素结束处的事件处理方法
uri:名字空间的URI(如果支持名字空间)
lname:返回元素的限定名,<bean>返回bean,而<util:list>返回list(如果支持名字空间)
qname:带前缀元素名(如果支持名字空间),如<util:list>将返回util:list
attrs:返回该元素全部属性对象
characters(char[] data,int index,int length):当遇到字符数据时的事件处理方法。
data:为XML字符串构成的数组(每次根据缓冲区大小进行传递向后滚动)
index:当前字符串中第一个字符在data中的位置
length:当前字符串长度
4、 SAX 编程方法
4.1、 工作原理:
<bookCase>
<book id="1">
<title>spring in action(中文版)</title>
</book>
</bookCase>
当一个SAXParser遇到以上的XML时,依次会调用:startDocument,startElement,startElement,startElement,characters(如内容很长可能会有若干次),endElement, endElement, endElement,endDocument。
4.2、 实现步骤:
(1)实现继承自DefalutHandler适配器的实现类,覆写“感兴趣”的方法。
(2)获得SAXParserFactory实例。
(3)由SAXParserFactory获得XMLReader实例。
(4)注册处理文档内容解析事件的ContentHandler
(5)调用XMLReader实例的parser方法,此时需给出“XML源”
示例:新建一个Android应用程序,在main.xml中添加一个按钮,当我们点击这个按钮时将会从本地tomcat服务器上下载一个xml文件,将xml文件的内容保存在String对象中。然后用SAX解析这个String对象。
需要说明的是xml源文件中各标签之间如果要有空格、Tap键等格式字符,因为SAX会把空格、Tab键解析成一个空白节点。这样的话可能会使程序不能输出我们想要显示的内容。在ContentHandler中重写处理空格的方法可以解决这个问题。这里为了简单起见,不再重写处理空格等字符的方法。
下载的xml文件:
]<?xml version="1.0" encoding="utf-8"?> <workers> <worker id="No1"> <name>Mark</name> <sex>male</sex> <status>CEO</status> <address>Beijing</address> <money>200000</money> </worker> <worker id="No2"> <name>Bill</name> <sex>male</sex> <status>CTO</status> <address>Beijing</address> <money>180000</money> </worker> <worker id="No3"> <name>Lucy</name> <sex>female</sex> <status>CFO</status> <address>Beijing</address> <money>180000</money> </worker> </workers>
源代码:
main.xml
]<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Button android:id="@+id/button" android:layout_width="300dp" android:layout_height="wrap_content" android:text="解析XML文件" /> </LinearLayout>
Android_xml.java
]package idea.org; import java.io.IOException; import java.io.StringReader; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class Android_xml extends Activity { private Button button; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); button=(Button)findViewById(R.id.button); button.setOnClickListener(new buttonClickListener()); } class buttonClickListener implements OnClickListener { /* (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { // TODO Auto-generated method stub new Thread() { public void run() { HttpDownloader httpDownloader=new HttpDownloader(); String xmlStr=httpDownloader.download("http://192.168.0.5:8080/Android/test.xml"); try { //获得SAXParser对象的工厂实例 SAXParserFactory saxParserFactory=SAXParserFactory.newInstance(); //获得XMLReader示例 XMLReader reader=saxParserFactory.newSAXParser().getXMLReader(); //注册处理XML文档内容解析事件的ContentHandler reader.setContentHandler(new MyContentHandler()); //开始解析string对象中所包含的XML资源 reader.parse(new InputSource(new StringReader(xmlStr))); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); } } }
MyContentHandler.java
]package idea.org; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class MyContentHandler extends DefaultHandler { private String name,sex,address,money,status,tagName; /* (non-Javadoc) * @see org.xml.sax.helpers.DefaultHandler#startDocument() */ @Override public void startDocument() throws SAXException { // TODO Auto-generated method stub System.out.println("--------开始解析--------"); } /* (non-Javadoc) * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) */ //遇到新的标签即新的元素时执行 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // TODO Auto-generated method stub tagName=localName;//以tagName的值来判断正在解析哪个标签 if(localName.equals("worker")) {//依次获取标签的全部属性 for(int i=0;i<attributes.getLength();i++) System.out.println(attributes.getLocalName(i)+"="+attributes.getValue(i)); } } /* (non-Javadoc) * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int) */ @Override public void characters(char[] ch, int start, int length) throws SAXException { // TODO Auto-generated method stub if(tagName.equals("name")) name=new String(ch,start,length); else if(tagName.equals("sex")) sex=new String(ch,start,length); else if(tagName.equals("status")) status=new String(ch,start,length); else if(tagName.equals("address")) address=new String(ch,start,length); else if(tagName.equals("money")) money=new String(ch,start,length); } /* (non-Javadoc) * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String) */ //标签解析完成之后执行 @Override public void endElement(String uri, String localName, String qName) throws SAXException { // TODO Auto-generated method stub tagName="";//清除tagName原来的值,这样在遇到空白节点时可以通过tagName识别出处理的是空白节点 if(localName.equals("worker")) {//打印出所有得到的数据 System.out.print("name:"+name); System.out.print(" sex:"+sex); System.out.print(" status:"+status); System.out.print(" address:"+address); System.out.println(" money:"+money); } } /* (non-Javadoc) * @see org.xml.sax.helpers.DefaultHandler#endDocument() */ @Override public void endDocument() throws SAXException { // TODO Auto-generated method stub System.out.println("--------解析结束--------"); } }
HttpDownloader.java
]package idea.org; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class HttpDownloader { private URL url=null; public String download(String urlStr) { StringBuffer stringbuffer=new StringBuffer(); String line; BufferedReader bufferReader=null; try { //创建一个URL对象 url=new URL(urlStr); //得到一个HttpURLConnection对象 HttpURLConnection httpUrlConnection=(HttpURLConnection) url.openConnection(); // 得到IO流,使用IO流读取数据 bufferReader=new BufferedReader(new InputStreamReader(httpUrlConnection.getInputStream())); while((line=bufferReader.readLine())!=null) { stringbuffer.append(line); } } catch(Exception e) { e.printStackTrace(); } return stringbuffer.toString(); } // 该函数返回整形 -1:代表下载文件出错 ;0:代表下载文件成功; 1:代表文件已经存在 public int download(String urlStr,String path,String fileName) { InputStream inputstream=null; FileUtils fileUtils=new FileUtils(); if(fileUtils.isExist(path+fileName)) return 1; else { try { inputstream=getFromUrl(urlStr); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } File file=fileUtils.writeToSDPATHFromInput(path, fileName, inputstream); if(file!=null) return 0; else return -1; } } //根据url字符串得到输入流 public InputStream getFromUrl(String urlStr) throws IOException { url=new URL(urlStr); HttpURLConnection httpUrlConnection=(HttpURLConnection) url.openConnection(); InputStream input=httpUrlConnection.getInputStream(); return input; } }
FileUtil.java
]package idea.org; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import android.os.Environment; public class FileUtils { private String SDPATH=null; public String getSDPATH() { return SDPATH; } public FileUtils() { //获得当前外部存储设备SD卡的目录 SDPATH=Environment.getExternalStorageDirectory()+"/"; } //创建文件 public File createFile(String fileName) throws IOException { File file=new File(SDPATH+fileName); file.createNewFile(); return file; } //创建目录 public File createDir(String fileName) throws IOException { File dir=new File(SDPATH+fileName); dir.mkdir(); return dir; } //判断文件是否存在 public boolean isExist(String fileName) { File file=new File(SDPATH+fileName); return file.exists(); } public File writeToSDPATHFromInput(String path,String fileName,InputStream inputstream) { File file=null; OutputStream outputstream=null; try { createDir(path); file=createFile(path+fileName); outputstream=new FileOutputStream(file); byte buffer[]=new byte[1024]; //将输入流中的内容先输入到buffer中缓存,然后用输出流写到文件中 while((inputstream.read(buffer))!=-1) { outputstream.write(buffer); } } catch(Exception e) { e.printStackTrace(); } finally { try { outputstream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return file; } }
AndroidManifest.xml
]<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="idea.org" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="11" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".Android_xml" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET"/> </manifest>
运行结果:
界面:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201912/09/487a36ca024d6e61a4b71bb42c9a968a.gif)
点击“解析XML文件”按钮打印以下内容:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201912/09/99c2683d8f9a3501f5236bbdcd1850c5.gif)
相关文章推荐
- Android开发之Pull解析XML文件
- Android开发之XML文件的解析的三种方法
- Android开发进阶(六)--PULL模式解析XML文件
- Android开发之XML文件的解析的三种方法
- android开发--mp3播放器项目源代码(xml文件解析,.lrc,.mp3文件下载,同时显示歌词)
- Android开发之XML文件解析的使用
- Android开发之XML文件的解析的三种方法
- Android开发之XML文件的解析的三种方法
- Android开发之使用pull解析XML文件
- Android开发之XML文件的解析的三种方法--转载(三)
- Android开发之XML文件解析
- Android开发之XML文件的解析的PULL方式解析
- Android开发(8)--Android中DOM解析xml文件
- Android开发之XML文件的解析的三种方法
- 【Android网络开发の3】XML之PULL方式 解析和生成XML文件
- Android开发之XML文件解析
- [置顶] Android开发之XML文件的解析
- Android应用开发之XML文件解析之一
- XML 文件解析 -- MarsChen Android 开发教程学习笔记
- Android开发之Pull解析读取和生成XML文件