android SAX解析XML
SAX(Simple API for XML)是一個解析速度快并且占用內存少的xml解析器,非常適合用于Android等移動設備。 SAX解析XML文件采用的是事件驅動,順序讀取XML文件,邊加載邊解析。也就是說,它并不需要解析完整個文檔,在按內容順序解析文檔的過程中,SAX會判斷當前讀到的字符是否合法XML語法中的某部分,如果符合就會觸發事件。(如:當遇到像文件開頭,文檔結束,或者標簽開頭與標簽結束時,會觸發一個事件,用戶通過在其回調事件中寫入處理代碼來處理XML文件,適合對XML的順序訪問,且是只讀的.)所謂事件,其實就是一些回調(callback)方法,這些方法(事件)定義在ContentHandler接口。在SAX接口中,事件源是org.xml.sax包總的XMLReader,它通過parser()方法來解析XML文檔,并產生事件。事件處理器是org.xml.sax包中的ContentHandler,DTDHandler,ErrorHandler,以及EntityResolver這4個接口。它們分別處理事件源在解析XML文檔過程中產生的不同種類的事件。
定義的事件處理類在實現該接口時,必須實現4個接口中的所有方法。在開發中不必直接從這4個接口直接繼承,因為org.xml.sax.helper包提供了類DefaultHandler,其繼承了這4個接口,在實際開發中直接從DefaultHandler繼承并實現相關函數就可以了并調用相應的監聽器設置方法(setXXXX()來完成與XMLReader事件源的連接),為了減少工作量,SDK提供了DefaultHandler類(適配器類)來做事件處理,主要的事件的回調方法如下:
方法 | 含義 |
---|---|
setDocumentLocator(Locator locator) | 設置一個可以定位文檔位置的對象 |
startDocument() | 用于處理文檔解析開始事件 |
startElement(String uri,String localName,String qName,Attrubutes) | 處理元素開始事件,從參數中可以獲取元素所在的RUL,元素名稱,屬性列表等信息 |
charachters(char[] ch,int start,int length) | 處理元素的字符內容,從參數中可以獲得內容 |
endElement(String uri,String localName,String qName) | 處理元素結束事件,參數中可以獲得元素所在URL,元素名稱等 |
endDocument() | 用于處理文檔解析的結束事件 |
各方法詳細說明:
startDocument()
當遇到文檔的開頭的時候,調用這個方法,可以在其中做一些預處理的工作。
endDocument()
和上面的方法相對應,當文檔結束的時候,調用這個方法,可以在其中做一些善后的工作。
startElement(String namespaceURI, String localName, String qName, Attributes atts)
當讀到一個開始標簽的時候,會觸發這個方法。namespaceURI就是命名空間,localName是不帶命名空間前綴的標簽名,qName是帶命名空間前綴的標簽名。通過atts可以得到所有的屬性名和相應的值。要注意的是SAX中一個重要的特點就是它的流式處理,當遇到一個標簽的時候,它并不會紀錄下以前所碰到的標簽,也就是說,在startElement()方法中,所有你所知道的信息,就是標簽的名字和屬性,至于標簽的嵌套結構,上層標簽的名字,是否有子元屬等等其它與結構相關的信息,都是不得而知的,都需要你的程序來完成。這使得SAX在編程處理上沒有DOM來得那么方便。
endElement(String uri, String localName, String name)
這個方法和上面的方法相對應,在遇到結束標簽的時候,調用這個方法。
characters(char[] ch, int start, int length)
這個方法用來處理在XML文件中讀到的內容,第一個參數為文件的字符串內容,后面兩個參數是讀到的字符串在這個數組中的起始位置和長度,使用new String(ch,start,length)就可以獲取內容。
通過XMLReader及DefaultHandler的配合來解析XML,基本思路如下:
創建SAXParserFactory對象:SAXParserFactory factory = SAXParserFactory.newInstance();
創建SAX解析器:SAXParser parser = factory.newSAXParser();
實例化一個DefaultHandler對象
將XML解析處理器(DefaultHandler對象)分配給解析器
對文檔進行解析,將每個事件發送給處理器,parser.parse(file, contentHandler);
通過DefaultHandler返回需要的數據集合
具體代碼如下:
domain:
package cn.itcast.domain;
public class Person {
private Integer id;
private String name;
private Short age;
public Person(){}
public Person(Integer id, String name, Short age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Short getAge() {
return age;
}
public void setAge(Short age) {
this.age = age;
}
@Override
public String toString() {
return "Person [age=" + age + ", id=" + id + ", name=" + name + "]";
}
}
service:
package cn.itcast.service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import cn.itcast.domain.Person;
/**
* 采用SAX解析XML內容
*/
public class SAXPersonService {
public List<Person> getPersons(InputStream inStream) throws Throwable{
//得到一個Sax解析器工廠
SAXParserFactory factory = SAXParserFactory.newInstance();
//得到解析器
SAXParser parser = factory.newSAXParser();
//new出一個PersonParser對象出來。把這個對象傳到下面語句中
PersonParser personParser = new PersonParser();
//對得到的輸入流Sax進行解析,第一個參數是要進行解析的xml內容,第二個參數是給 SAX DefaultHandler使用(回調函數)
parser.parse(inStream, personParser);
inStream.close();
//返回得到的getPersons
return personParser.getPersons();
}
private final class PersonParser extends DefaultHandler{
//把解析到的數據都放到集合里面去
private List<Person> persons = null;
//記錄當前所解析到的元素節點名稱
private String tag = null;
private Person person = null;
//提供一個getpersons方法,主要是為主程序使用
public List<Person> getPersons() {
return persons;
}
@Override
public void startDocument() throws SAXException {
//初始化
persons = new ArrayList<Person>();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//判斷是不是我們要解析的元素節點
if("person".equals(localName)){
person = new Person();//new出person對象,把要解析的內容傳給person的Id屬性
person.setId(new Integer(attributes.getValue(0)));
}
//存放節點名稱到成員變量里面
tag = localName;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//首先判斷節點名稱是否為空,然后在判斷節點名稱是否為name
if(tag!=null){
String data = new String(ch, start, length);//獲取文本節點的數據
if("name".equals(tag)){//判斷節點名稱是否為name
person.setName(data);//把要解析的內容傳給person的name屬性
}else if("age".equals(tag)){//判斷節點名稱是否為age
person.setAge(new Short(data));
}
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("person".equals(localName)){//當跟末節點為person時
persons.add(person);//把person放到集合persons里面
person = null;//把當前person設為空
}
//遇到結束元素就把記錄設為空
tag = null;
}
}
}
Activity或測試類:
public class PersonServiceTest extends AndroidTestCase {
private static final String TAG = "PersonServiceTest";
public void testSAXGetPersons() throws Throwable{
//new出一個業務對象
SAXPersonService service = new SAXPersonService();
//通過類加載器加載要解析的文件
InputStream inStream = getClass().getClassLoader().getResourceAsStream("itcast.xml");
List<Person> persons = service.getPersons(inStream);
for(Person person : persons){
Log.i(TAG, person.toString());
}
}
}
AndroidMainFest文件代碼,這里主要是用到了單元測試,需要加幾句代碼:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.itcast.xml"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<uses-library android:name="android.test.runner" />
<activity android:name=".MainActivity"
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-sdk android:minSdkVersion="8" />
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="cn.itcast.xml" android:label="Tests for My App" />
</manifest>
智能推薦
Android開發:XML簡介及DOM、SAX、PULL解析對比
目錄 目錄 定義 XML(extensible Markup Language) ,是一種數據標記語言 & 傳輸格式 作用 對數據進行標記(結構化數據) 對數據進行存儲 對數據進行傳輸 與html的區別:html用于顯示信息;xml用于存儲&傳輸信息 XML特點 標簽可進行自定義 XML允許作者定義自己的標簽和文檔結構 自我描述性 XML文檔實例 僅僅是一個純文本,有文本處理能力的...
Android使用Sax 及Pull 解析Xml demo
客戶端開發中,越來越多的接口使用的數據傳輸類型時json了,xml相對較少。恰好當前要使用到了xml傳遞數據,寫個demo權當記錄安卓中如何使用sax 及 pull解析xml. 1.常用的幾種解析XML的方式 Dom ,Sax ,Pull Dom解析Xml 是將整個Xm文檔當成一個對象來處理,會先把整個文檔讀入到內存里。是基于樹的結構,通常需要加載整文檔和構造DOM樹,然...
我的Android進階之旅------>Android中解析XML 技術詳解---->SAX解析、DOM解析、PULL解析...
XML在各種開發中都廣泛應用,Android也不例外。作為承載數據的一個重要角色,如何讀寫XML成為Android開發中一項重要的技能。今天就由我向大家介紹一下在Android平臺下幾種常見的XML解析和創建的方法。 在Android中,常見的XML解析器分別為SAX解析器、DOM解析器和PULL解析器,下面,我將一一向大家詳細介紹。 SAX解析器: SAX(Simple API for XML)...
android解析XML文件的三方法之SAX
采用DOM方法讀取XML文檔,由于使用DOM方法需要將整個XML文檔加載內存中,對系統資源占用比較多,這對內存比較緊張的Android系統來說,使用 DOM方法讀取XML文檔會有很大的限制。 使用SAX方法讀取XML,對內存資源的占用的比較少,因此在嵌入式設備中極力推薦使用,Android也不例外,本篇幅詳細說明Android中如何使用SAX讀取XM...
深入分析android中用SAX解析XML文件并糾錯
在android中解析XML文件有很多方法,今天主要介紹下SAX解析。 1、SAX簡介 SAX是基于事件驅動模型,可以捕獲到讀取文檔過程中產生的事件,比如開始文檔、結束文檔、開始元素、結束元素、文本內容事件等。通過定義一個事件處理器,在這些事件觸發后,來實現數據的獲取。通過使用XMLReader類來注冊事件處理器,在Android中有如下4個事件處理器接口,如下圖: 補充:事件驅動模型是事件源發出...
猜你喜歡
Xml 解析:(sax 解析)
sax解析的原理() 解析xml有兩種技術 dom 和sax 根據xml的層級結構在內存中分配一個樹形結構 把xml中標簽,屬性,文本封裝成對象 sax方式:事件驅動,邊讀邊解析 &nb...
XML的SAX解析
SAX是一個順序執行,事件驅動的解析方法(事件驅動,簡單地說就是你點什么按鈕(即產生什么事件)) SAX的工作原理; DOM解析博客地址連接:DOM解析 SAX與DOM解析的優點;SAX解析適合較大的XML文件解析,DOM可以增加節點 SAX解析的主要方法; JAVA...
SAX-解析XML
基于SAX的xml解析 sax通常用來進行查找,就是搜索使用,大概流程如下 解析器工廠 解析器 XMLReader 處理器ContentHandler,這部分需要程序員自己寫 進行遍歷和指定位置查找 小結 SAX的優勢在于,找多少就加載多少,不會一下子擠滿內存,但是缺點是比較麻煩- -,處理部分 得程序員自己手寫,其實也還好.做個筆記把...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...