編輯:關於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 Liststudents; 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的新特性,我們必須導入5.X的支持包FloatingActionButtonAndroid 的新的設計規范中具有陰影效果的懸浮窗按鈕
一.MVP理論簡介1.為何要在android中引入MVP??在Android項目中,Activity和Fragment占據了大部分的開發工作。而MVP設計模式可以優化Ac
本文由阿裡巴巴移動安全客戶端、YunOS資深工程師Hao(嵌入式企鵝圈原創團隊成員)撰寫,是Hao在嵌入式企鵝圈發表的第一篇原創文章,對Android無線開發
第3節 控制LED燈現在我們開始嘗試用代碼控制一個真正的直觀的硬件設備。第一個例子:讓Arduino開發板上的一個LED小燈周期性的打開、關閉。第二個例子:讓LED燈亮度