原文地址:http://blog.csdn.net/ichliebephone/article/details/5971533
Xml文件有許多解析方式,在學習J2EE中就學過很多,比如DOM,DOM4j,SAX,JDOM等等。
在Android中,比較常見的有SAX,DOM和Pull這三種解析方式。並且Android上對XML解析的支持是相當強大的,看一下 Android 中和 XML 解析相關的包:
1. android.sax
這是Android SDK提供的sax解析的包,因爲可以對具體的Element 設置監聽進行處理,因此有更好魯棒性。
2. android.util.Xml
這是android.util包中的其中一個類,提供XML相關的實用方法,而且都是public static形式的類方法,即可以直接以類名調用。
3. javax.xml.parsers
這是使用原來Java SDK用於xml處理的API ,即 JAXP( Java API for XML Processing),主要提供了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例子。
下面就看看這三種解析方法的第一種:SAX解析技術
SAX(Simple API for XML)是基於事件驅動的 XML 處理模式,主要是圍繞着事件源以及事件處理器(或者叫監聽器)來工作的。一個可以產生事件的對象被稱爲事件源,而可以針對事件產生響應的對象就被叫做事件處理器。事件源和事件處理器是通過在事件源中的事件處理器註冊方法連接的。這樣當事件源產生事件後(比如碰到XML元素的開始和結束等),調用事件處理器(由許多回調函數組成) 相應的處理方法,一個事件就獲得了處理。當然在事件源調用事件處理器中特定方法的時候,會傳遞給事件處理器相應事件的狀態信息 (即回調函數中的參數) ,這樣事件處理器才能夠根據事件信息來決定自己的行爲。
其中常用的事件處理回調函數有用於文檔處理的
文檔開始:startDocument(),
文檔結束:endDocument() ,
XML元素開始:startElement(String uri, String localName, String qName,Attributes attributes),
XML元素內容:characters(char[] ch, int start, int length) ,
XML元素結束:endElement(String uri, String localName, String qName),
還有解析錯誤的回調函數error(SAXParseException exception)等。
在Android系統中,提供了兩種SAX 解析的包,一種是原來Java SDK就有的用於XML處理的API(稱爲JAXP:Java API for XML Processing,包含了SAX和DOM 兩者相關的 API),相關內容在包javax.xml.parsers中。還有一種是經過了 Android SDK包裝了之後的sax包,相關內容在包 android.sax 中。
這部分我們先來學習原來Java SDK就有的用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 ,or EntityResover)
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, and SAX InputSources等四種形式。
實現步驟和上面類似:
1. 在繼承DefaultHandler的類裏面重寫需要的回調函數
2. 創建SAXParser實例
3. SAXParser實例調用parse方法啓動解析
我們要解析這樣一個簡單的xml文件 test.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <persons>
- <person id="1">
- <name>Lucy</name>
- <age>15</age>
- </person>
- <person id="2">
- <name>Tim</name>
- <age>20</age>
- </person>
- </persons>
xml文件中的節點分爲兩種,元素節點和文本節點。
元素節點指的是 <>中的元素
文本節點指的是 元素與元素之間的文本
解析xml文件時 ,應該從開始一步步往下解析, 對自己感興趣的觸發事件,在回調方法裏面的寫好事件處理。
一般需要重寫5個方法:
startDocument() :開始文檔的回調方法
endDocument() :結束文檔的回調方法
startElement(String uri, String localName, String qName, Attributes attributes) :開始元素節點的回調方法
參數:
uri
- 名稱空間 URI,如果元素沒有任何名稱空間 URI,或者沒有正在執行名稱空間處理,則爲空字符串。
localName
- 本地名稱(不帶前綴),如果沒有正在執行名稱空間處理,則爲空字符串。
qName
- 限定的名稱(帶有前綴),如果限定的名稱不可用,則爲空字符串。
attributes
- 附加到元素的屬性。如果沒有屬性,則它將是空的 Attributes 對象。
endElement(String uri, String localName, String qName)
參數:
uri
- 名稱空間 URI,如果元素沒有任何名稱空間 URI,或者沒有正在執行名稱空間處理,則爲空字符串。
localName
- 本地名稱(不帶前綴),如果沒有正在執行名稱空間處理,則爲空字符串。
qName
- 限定的名稱(帶有前綴),如果限定的名稱不可用,則爲空字符串。
characters(char[] ch, int start, int length)
參數:
ch
- 字符。
start
- 字符數組中的開始位置。
length
- 從字符數組中使用的字符數。
在實際操作中根據需求,在API中參照更多的方法。
- package com.tao.xmlparse;
- import java.util.ArrayList;
- import java.util.List;
- import org.xml.sax.Attributes;
- import org.xml.sax.SAXException;
- import org.xml.sax.helpers.DefaultHandler;
- public class SaxHandler extends DefaultHandler{
- private String tag;//標誌標籤的名稱
- private List<Person> persons;
- private Person person;
- //開始文檔的回調方法
- @Override
- public void startDocument() throws SAXException {
- super.startDocument();
- persons=new ArrayList<Person>();
- }
- //結束文檔的回調方法
- @Override
- public void endDocument() throws SAXException {
- super.endDocument();
- }
- //開始元素的回調方法
- @Override
- public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
- super.startElement(uri, localName, qName, attributes);
- if("person".equals(localName)){
- person=new Person();
- person.setId(new Integer(attributes.getValue(0)));
- }else if("name".equals(localName)){
- tag=localName;
- }else if ("age".equals(localName)) {
- tag=localName;
- }
- }
- //結束元素的回調方法
- @Override
- public void endElement(String uri, String localName, String qName) throws SAXException {
- super.endElement(uri, localName, qName);
- tag=null;
- if("person".equals(localName)){
- persons.add(person);
- person=null;
- }
- }
- //解析到文本節點回調方法
- @Override
- public void characters(char[] ch, int start, int length) throws SAXException {
- super.characters(ch, start, length);
- if(tag==null)
- return;
- if("name".equals(tag)){
- person.setName(new String(ch,start,length));
- }if("age".equals(tag)){
- person.setAge(new Integer(new String(ch,start,length)));
- }
- }
- //返回解析的數據
- public List<Person> getResult(){
- return persons;
- }
- }
Person Mode類
- package com.tao.xmlparse;
- public class Person {
- private int id;
- private String name;
- private int age;
- public Person() {
- }
- public Person( String name, int age) {
- this.name = name;
- this.age = age;
- }
- public Person(int id, String name, int age) {
- this.id = id;
- this.name = name;
- this.age = age;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- }
2. 創建SAXParser實例 3. SAXParser實例調用parse方法啓動解析
- public void saxParseXml() throws ParserConfigurationException, SAXException, IOException{
- //構造解析器,創建SAXParser實例
- SAXParserFactory factory=SAXParserFactory.newInstance();
- SAXParser parser=factory.newSAXParser();
- //獲得xml文件的輸入流
- InputStream inputStream=getClass().getClassLoader().getResourceAsStream("test.xml");
- //初始化hanlder對象
- SaxHandler handler=new SaxHandler();
- //開始解析
- parser.parse(inputStream, handler);
- //返回解析結果,然後輸出
- List<Person> persons=handler.getResult();
- for (Person p:persons) {
- System.out.println(p.getId()+"--"+p.getName()+"---"+p.getAge());
- }
- }