編輯:關於Android編程
最近用到了XML數據 ,今天分享一下我對SAX的理解
原理 實例sax 是基於事件驅動。那麼什麼是事件驅動呢(請自行百度)簡單點說 就是觸發一個事件 去執行某些操作;
sax在解析XML時 是邊讀取邊解析,不會將整個文檔加載到內存中。而是讀到一個元素解析一個元素,和上下的元素是關聯不上的,占用內存較小。這也是非常適合Android這種內存較小的嵌入式設備內存的原因;
sax在讀取文檔的時候激活一系列的事件並執行一些操作。
在開始讀取文檔的時候觸發 startDocument() ;
讀取到一個元素觸發 startElement();
讀取文本 觸發characters(); ps:即使是讀取到換行符也會觸發
元素讀取完畢 觸發 endElement();
讀取完整個文檔觸發 endDocument();
上述事件 基本就把xml文檔讀取完畢了,這些方法在DefaultHandle中已經封裝好了,我們做的就是重寫這些方法就可以了
student XML文件
張三 13班 17
創建 StudentHandler 繼承自 DefaultHandler
package com.skymxc.demo.parsexml;
import android.text.TextUtils;
import android.util.Log;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
/**
* Created by sky-mxc
*/
public class StudentHandler extends DefaultHandler {
private List students;
private Student student;
private String tag; //記錄讀取到的元素的名字
@Override
public void startDocument() throws SAXException {
Log.e("Tag","=======startDocument()========");
students = new ArrayList<>();
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
Log.e("Tag","=======endDocument()========");
}
/**
*
* @param uri 明明空間的uri
* @param localName 不帶前綴的元素名字
* @param qName 帶有前綴的元素名
* @param attributes 屬性
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
Log.e("Tag","==========startElement()==========="+localName);
Log.e("Tag","===startElement():uri======"+uri);
Log.e("Tag","===startElement():localName======"+localName);
Log.e("Tag","===startElement():qName======"+qName);
switch (localName){
case "Student": //student元素
student = new Student();
int id = Integer.parseInt(attributes.getValue("id")); //獲取到屬性id的值
student.setId(id);
break;
default:
tag=localName;//除了 student元素 其他元素都要讀取文本 characters()無法獲取元素名字
break;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
Log.e("Tag","==========endElement()==========="+localName);
switch (localName){
case "Student":
students.add(student);
break;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
Log.e("Tag","==========characters()===========");
Log.e("Tag","======start:"+start);
Log.e("Tag","======length:"+length);
//將字符轉為字符串
String text = new String(ch,start,length).trim();
Log.e("Tag","====當前元素:"+tag+"===文本值:"+text);
//排除無效字符 會讀取到一些換行符
if (TextUtils.isEmpty(text)) return;
if (student == null) return;
switch (tag){
case "name":
student.setName(text);
break;
case "age":
int age = Integer.parseInt(text);
student.setAge(age);
break;
case "clazz":
student.setClazz(text);
break;
}
}
public List getStudents() {
return students;
}
}
Handler中的執行過程解析 讀取過程如下,可以看出 就算根節點沒有文本也觸發了characters() 因為會讀取換行符 所以慎重處理
E/Tag: =======startDocument()======== E/Tag: ==========startElement()===========Students E/Tag: ==========characters()=========== E/Tag: ==========characters()=========== E/Tag: ==========startElement()===========Student E/Tag: ==========characters()=========== E/Tag: ==========characters()=========== E/Tag: ==========startElement()===========name E/Tag: ==========characters()=========== E/Tag: ==========endElement()===========name E/Tag: ==========characters()=========== E/Tag: ==========characters()=========== E/Tag: ==========startElement()===========clazz E/Tag: ==========characters()=========== E/Tag: ==========endElement()===========clazz E/Tag: ==========characters()=========== E/Tag: ==========characters()=========== E/Tag: ==========startElement()===========age E/Tag: ==========characters()=========== E/Tag: ==========endElement()===========age E/Tag: ==========characters()=========== E/Tag: ==========characters()=========== E/Tag: ==========endElement()===========Student E/Tag: ==========characters()=========== E/Tag: ==========endElement()===========Students E/Tag: =======endDocument()========
startElement() 參數如下 xml 文件中並沒有定義 命名空間 和任何前綴
uri :為空
qName :也是元素的名字並沒有帶有前綴
localName: 當前元素的名字
E/Tag: ===startElement():uri====== E/Tag: ===startElement():localName======Student E/Tag: ===startElement():qName======Student E/Tag: ==========characters()===========
characters()參數如下
start :開始下標
length :長度
E/Tag: ==========characters()=========== E/Tag: ======start:0 E/Tag: ======length:3 E/Tag: ====當前元素:clazz===文本值:13班
創建SAXParse 設置解析內容
SAXParserFactory factory = SAXParserFactory.newInstance();
StudentHandler handler = new StudentHandler();
try {
SAXParser parser = factory.newSAXParser();
parser.parse(getAssets().open("students.xml"),handler);
Log.e("Tag","===Size:"+handler.getStudents().size());
for (Student stu :handler.getStudents()){
Log.e("Tag","==Name:"+stu.getName()+"===Age:"+stu.getAge()+"====Clazz:"+stu.getClazz()+"==id:"+stu.getId());
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
讀取結果
E/Tag: ==Name:張三===Age:17====Clazz:13班==id:0
對於SAX的理解就這些了
為什麼只有深夜 才有感覺呢,唉…..發愁
github地址 :https://github.com/sky-mxc/AndroidDemo/tree/master/parsexml
Android 5.X新特性
首先,如果要使用Android 5.X的新特性,我們必須導入5.X的支持包FloatingActionButtonAndroid 的新的設計規范中具有陰影效果的懸浮窗按鈕
MVP架構實踐
一.MVP理論簡介1.為何要在android中引入MVP??在Android項目中,Activity和Fragment占據了大部分的開發工作。而MVP設計模式可以優化Ac
Android無線開發的幾種常用技術綜述
本文由阿裡巴巴移動安全客戶端、YunOS資深工程師Hao(嵌入式企鵝圈原創團隊成員)撰寫,是Hao在嵌入式企鵝圈發表的第一篇原創文章,對Android無線開發
手把手教你智能硬件開發(三) 控制LED燈
第3節 控制LED燈現在我們開始嘗試用代碼控制一個真正的直觀的硬件設備。第一個例子:讓Arduino開發板上的一個LED小燈周期性的打開、關閉。第二個例子:讓LED燈亮度