Android中使用sax解析xml文件的方法
SAX是一個(gè)解析速度快并且占用內(nèi)存少的xml解析器,非常適合用于Android等移動(dòng)設(shè)備。 SAX解析XML文件采用的是事件驅(qū)動(dòng),也就是說,它并不需要解析完整個(gè)文檔,在按內(nèi)容順序解析文檔的過程中,SAX會(huì)判斷當(dāng)前讀到的字符是否合法XML 語法中的某部分,如果符合就會(huì)觸發(fā)事件。所謂事件,其實(shí)就是一些回調(diào)(callback)方法,這些方法(事件)定義在ContentHandler接口。下面是一些ContentHandler接口常用的方法:
startDocument():當(dāng)遇到文檔的開頭的時(shí)候,調(diào)用這個(gè)方法,可以在其中做一些預(yù)處理的工作。
endDocument():和上面的方法相對(duì)應(yīng),當(dāng)文檔結(jié)束的時(shí)候,調(diào)用這個(gè)方法,可以在其中做一些善后的工作。
startElement(String namespaceURI, String localName, String qName, Attributes atts)
當(dāng)讀到一個(gè)開始標(biāo)簽的時(shí)候,會(huì)觸發(fā)這個(gè)方法。 namespaceURI就是命名空間,localName是不帶命名空間前綴的標(biāo)簽名,qName是帶命名空間前綴的標(biāo)簽名。通過atts可以得到所有的屬性名和相應(yīng)的值。要注意的是SAX中一個(gè)重要的特點(diǎn)就是它的流式處理,當(dāng)遇到一個(gè)標(biāo)簽的時(shí)候,它并不會(huì)紀(jì)錄下以前所碰到的標(biāo)簽,也就是說,在 startElement()方法中,所有你所知道的信息,就是標(biāo)簽的名字和屬性,至于標(biāo)簽的嵌套結(jié)構(gòu),上層標(biāo)簽的名字,是否有子元屬等等其它與結(jié)構(gòu)相關(guān)的信息,都是不得而知的,都需要你的程序來完成。這使得SAX在編程處理上沒有DOM來得那么方便。
endElement(String uri, String localName, String name):這個(gè)方法和上面的方法相對(duì)應(yīng),在遇到結(jié)束標(biāo)簽的時(shí)候,調(diào)用這個(gè)方法。
characters(char[] ch, int start, int length) :這個(gè)方法用來處理在XML文件中讀到的內(nèi)容,第一個(gè)參數(shù)為文件的字符串內(nèi)容,后面兩個(gè)參數(shù)是讀到的字符串在這個(gè)數(shù)組中的起始位置和長(zhǎng)度,使用new String(ch,start,length)就可以獲取內(nèi)容。
注意:一個(gè)標(biāo)簽之間的字符比較多時(shí),或者字符串中包含有”\n”等特殊字符時(shí),就會(huì)出現(xiàn)字符丟失的現(xiàn)象。遇到這種問題不要懷疑SAX不能解析標(biāo)簽中含有”\n”或字符比較多的XML。實(shí)際上是我們寫的Handler是有問題的。SAX在解析XML時(shí),當(dāng)遇到一個(gè)標(biāo)簽中的內(nèi)容比較多時(shí),就會(huì)多次調(diào)用characters。所以我們?cè)趯慔andler時(shí)要考慮到這種情況。就不會(huì)丟字符了。以下是一種解決方案:新建一個(gè)臨時(shí)變量temp,在調(diào)用characters方法中用temp接收數(shù)據(jù),在endElement方法中把臨時(shí)變量temp賦值給目標(biāo)變量,并給臨時(shí)變量temp清空,避免出現(xiàn)臟數(shù)據(jù),這樣就可以解決sax讀取XML時(shí)不能讀取換行符號(hào)后面的內(nèi)容的問題。 import java.io.Serializable; /** public Person() { public Person(String name, Short age) { public Integer getId() { public void setId(Integer id) { public String getName() { public void setName(String name) { public Short getAge() { public void setAge(Short age) { } import java.util.ArrayList; import org.xml.sax.Attributes; import com.ljq.entity.Person; //getter... import java.io.InputStream; import javax.xml.parsers.SAXParser; import com.ljq.entity.Person; /** } import java.io.InputStream; import com.ljq.entity.Person; import android.test.AndroidTestCase; public class SaxPersonServiceTest extends AndroidTestCase{
ljq.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>李明</name>
<age>30</age>
</person>
<person id="20">
<name>李向梅</name>
<age>25</age>
</person>
</persons>
實(shí)體類
package com.ljq.entity;
* 實(shí)體類
*
* @author jiqinlin
*
*/
@SuppressWarnings("serial")
public class Person implements Serializable{
private Integer id;
private String name;
private Short age;
}
super();
this.name = name;
this.age = age;
}
return id;
}
this.id = id;
}
return name;
}
this.name = name;
}
return age;
}
this.age = age;
}
handle類
package com.ljq.service;
import java.util.List;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XMLContentHandler extends DefaultHandler {
//臨時(shí)變量,解決sax讀取XML時(shí)不能讀取換行符號(hào)后面的內(nèi)容的問題;注意temp=""不能寫成temp或temp=null,避免臟數(shù)據(jù)
private String temp="";
private String preTag;
private Person person;
private List<Person> persons;
@Override
public void startDocument() throws SAXException {
persons = new ArrayList<Person>();
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (person!=null){
String date = new String(ch,start,length);
if ("name".equals(preTag)) {
temp+=date;
}else if ("age".equals(preTag)) {
temp+=date;
}
}
}
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
if ("person".equals(localName)) {
person= new Person();
person.setId(attributes.getIndex("id"));
}
preTag = localName;
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
if (person !=null && "name".equals(localName)) {
person.setName(temp);
temp="";
}else if (person !=null && "age".equals(localName)) {
person.setAge(new Short(temp));
temp="";
}else if (person !=null && "person".equals(localName)) {
persons.add(person);
person = null;
}
preTag = null;
}
public List<Person> getPersons() {
return persons;
}
}
package com.ljq.service;
import java.util.List;
import javax.xml.parsers.SAXParserFactory;
* sax解析工廠
*
* @author jiqinlin
*
*/
public class SaxPersonService {
// 業(yè)務(wù)層要對(duì)外拋出
public static List<Person> readXML(InputStream inStream) throws Exception {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser(); // 創(chuàng)建解析器
// 設(shè)置解析器的相關(guān)特性,http://xml.org/sax/features/namespaces = true
// 表示開啟命名空間特性
// saxParser.setProperty("http://xml.org/sax/features/namespaces",true);
XMLContentHandler handler = new XMLContentHandler();
saxParser.parse(inStream, handler);
inStream.close();
return handler.getPersons();
}
測(cè)試類
package com.ljq.test;
import java.util.List;
import com.ljq.service.SaxPersonService;
import android.util.Log;
private final String TAG = "SaxPersonServiceTest";
public void testReadXML() throws Exception{
//ljq.xml放在src目錄下
InputStream inputStream = SaxPersonServiceTest.class.getClassLoader().getResourceAsStream("ljq.xml");
List<Person> persons = SaxPersonService.readXML(inputStream);
for(Person person : persons){
Log.i(TAG, person.getId() + " : " + person.getName() + " : " + person.getAge());
}
}
}
運(yùn)行結(jié)果

在android模擬器中,如果是中文字符會(huì)出現(xiàn)亂碼,在真機(jī)上就不會(huì)出現(xiàn)這種情況
- Android 解析XML 文件的四種方法總結(jié)
- Android中使用PULL方式解析XML文件深入介紹
- Android 使用Pull方法解析XML文件的方法
- Android開發(fā)之XML文件解析的使用
- android編程之XML文件解析方法詳解(附源碼)
- Android中使用pull解析器操作xml文件的解決辦法
- Android使用Pull解析器解析xml文件的實(shí)現(xiàn)代碼
- android開發(fā)基礎(chǔ)教程—三種方式實(shí)現(xiàn)xml文件解析
- Android開發(fā)之DOM解析xml文件的方法
- Android中對(duì)xml文件解析的3種方式總結(jié)
相關(guān)文章
Android里實(shí)現(xiàn)退出主程序的提示代碼
當(dāng)用戶選擇"確定",就退出當(dāng)前的對(duì)話框。其中,有個(gè)很重要的函數(shù),Activity.finish(),通過調(diào)用這個(gè)函數(shù),退出當(dāng)前運(yùn)行的整個(gè)Android程序2013-06-06
Android activity堆棧及管理實(shí)例詳解
這篇文章主要介紹了Android activity堆棧及管理實(shí)例詳解的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,對(duì)android activity堆棧相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-09-09
Android實(shí)現(xiàn)圖片異步加載及本地緩存
這篇文章主要介紹了Android實(shí)現(xiàn)圖片異步加載及本地緩存的相關(guān)資料,需要的朋友可以參考下2016-02-02
Android提高之TelephonyManager功能探秘
這篇文章主要介紹了Android的TelephonyManager功能,可以幫助讀者更好的理解Java反射機(jī)制,需要的朋友可以參考下2014-08-08
Android編程之SurfaceView學(xué)習(xí)示例詳解
這篇文章主要介紹了Android編程之SurfaceView學(xué)習(xí)示例,結(jié)合實(shí)例分析了SurfaceView的功能、使用方法與注意事項(xiàng),具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10
android使用ViewPager實(shí)現(xiàn)輪播效果
這篇文章主要為大家詳細(xì)介紹了android使用ViewPager實(shí)現(xiàn)輪播效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04

