在Android系統中,對於XML文件的讀取主要採用的是SAX方法。SAX是一個用於處理XML事件驅動的“推”模型,雖然它不是W3C標準,但它卻是一個得到了廣泛認可的API。SAX解析器不像DOM那樣建立一個完整的文檔樹,而是在讀取文檔時激活一系列事件,這些事件被推給事件處理器,然後由事件處理器提供對文檔內容的訪問。
常見的事件處理器有三種基本類型:
a. 用於訪問XML DTD內容的DTDHandler;
b. 用於低級訪問解析錯誤的ErrorHandler;
c. 用於訪問文檔內容的ContentHandler,這也是最普遍使用的事件處理器。
因爲SAX具有邊掃描邊讀取的特性,無需將整個文件讀入內存中,更好的節省了移動設備中的資源。但是這種方法對於操作節點顯得略有複雜。
下面以本人在學習中所看過的一個視頻教程中的實例,說明Android應用程序對於XML文檔的解析過程。
用於開啓解析的Activity:
- public class XMLActitity extends Activity {
-
- private Button parseButton ;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- parseButton = (Button)findViewById(R.id.parseButton);
- parseButton.setOnClickListener(new ParseButtonListener());
- }
- //設定監聽器,當點擊按鈕時,開始進行解析。
- class ParseButtonListener implements OnClickListener{
-
- @Override
- public void onClick(View v) {
- HttpDownloader hd = new HttpDownloader();
- //將網絡上的一個XML資源下載並解析成爲一個字符串,這裏的解析在一個外部類中進行,這裏不再列出。
- String resultStr = hd.download("http://192.168.1.107:8081/voa1500/test.xml");
- System.out.println(resultStr);
- try{
- //下面是解析XML的
-
- SAXParserFactory factory = SAXParserFactory.newInstance(); //2
- XMLReader reader = factory.newSAXParser().getXMLReader();
-
- reader.setContentHandler(new MyContentHandler());
-
- reader.parse(new InputSource(new StringReader(resultStr)));
-
- }
- catch(Exception e){
- e.printStackTrace();
- }
- }
-
- }
- }
|
內容處理器:
SAX時間作爲驅動的解析模型,需要相應的事件處理函數。SAX將不同的事件處理函數按照類型分不同接口中。對於文件內容的處理函數,在內容處理器接口(ContentHandler)中。
- public class MyContentHandler extends DefaultHandler {
- String hisname, address, money, sex, status;
- String tagName;
-
- //當開始解析文檔時,觸發這個函數
- public void startDocument() throws SAXException {
- System.out.println("````````begin````````");
- }
- //當結束解析文檔時,觸發這個函數
- public void endDocument() throws SAXException {
- System.out.println("````````end````````");
- }
- //當掃描到開始標籤時,觸發這個函數。
- public void startElement(String namespaceURI, String localName,
- String qName, Attributes attr) throws SAXException {
- //使用全局變量tagName作爲當前正在解析節點的標記。
- tagName = localName;
- if (localName.equals("worker")) {
-
- for (int i = 0; i < attr.getLength(); i++) {
- //打印其中某個屬性的名稱和屬性值
- System.out.println(attr.getLocalName(i) + "=" + attr.getValue(i));
- }
- }
- }
-
- public void endElement(String namespaceURI, String localName, String qName)
- throws SAXException {
-
- tagName = "";
- if (localName.equals("worker")) {
- this.printout();
- }
- }
- //當掃描到標籤內容時,觸發這個函數。標籤的內容存儲在字符數組中。
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- //首先判斷當前掃描到的標籤,然後根據當前標籤判斷標籤內容
- if (tagName.equals("name"))
- hisname = new String(ch, start, length);
- else if (tagName.equals("sex"))
- sex = new String(ch, start, length);
- else if (tagName.equals("status"))
- status = new String(ch, start, length);
- else if (tagName.equals("address"))
- address = new String(ch, start, length);
- else if (tagName.equals("money"))
- money = new String(ch, start, length);
- }
-
- private void printout() {
- System.out.print("name: ");
- System.out.println(hisname);
- System.out.print("sex: ");
- System.out.println(sex);
- System.out.print("status: ");
- System.out.println(status);
- System.out.print("address: ");
- System.out.println(address);
- System.out.print("money: ");
- System.out.println(money);
- System.out.println();
- }
-
- }
|
在上面程序中,需要注意,我們並非實現了ContentHandler接口,而是繼承了已經實現該接口的DefaultHandler。我再付類中已經實現了接口中所有方法,並將方法實現爲空方法,我們繼承父類只需要重寫那些我們需要的方法即可。