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 語(yǔ)法中的某部分,如果符合就會(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)的信息,都是不得而知的,都需要你的程序來(lái)完成。這使得SAX在編程處理上沒有DOM來(lái)得那么方便。
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è)方法用來(lái)處理在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í)戰(zhàn)教程第十篇仿騰訊手機(jī)助手小火箭發(fā)射效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)戰(zhàn)教程第十篇仿騰訊手機(jī)助手小火箭發(fā)射效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
Android使用DisplayManager創(chuàng)建虛擬屏流程及原理解析
這篇文章主要介紹了Android使用DisplayManager創(chuàng)建虛擬屏流程及原理解析,DisplayManager提供了createVirtualDisplay接口,用于創(chuàng)建虛擬屏,虛擬屏可以把屏幕分出不同的區(qū)域,需要的朋友可以參考下2024-05-05
Android Gridview布局出現(xiàn)滾動(dòng)條或組件沖突解決方法
這篇文章主要介紹了Android Gridview布局出現(xiàn)滾動(dòng)條或組件沖突解決方法,GridView是一個(gè)在二維可滾動(dòng)的網(wǎng)格中展示內(nèi)容的控件。網(wǎng)格中的內(nèi)容通過使用adapter自動(dòng)插入到布局中2022-07-07
android:照片涂畫功能實(shí)現(xiàn)過程及原理詳解
這篇文章主要介紹了android:照片涂畫功能實(shí)現(xiàn)過程及原理,需要的朋友可以參考下2014-02-02
Android 開機(jī)充電圖標(biāo)和充電動(dòng)畫效果
這篇文章主要介紹了Android 開機(jī)充電圖標(biāo)和充電動(dòng)畫效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12
Android自定義View實(shí)現(xiàn)豎向滑動(dòng)回彈效果
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)滑動(dòng)回彈效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Android檢測(cè)url地址是否可達(dá)的兩種方法
今天小編就為大家分享一篇Android檢測(cè)url地址是否可達(dá)的兩種方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2019-01-01

