:Android網路程式設計--XML之解析方式:SAX

wangyy發表於2015-04-23

任何放置在資源(res)目錄下的內容可以通過應用程式的R類訪問,這是被Android編譯過的,而任何放置在資產(assets)目錄下的內容會保持它的原始檔案格式,為了讀取它們,必須使用AssetManager來以位元組流的方式讀取檔案,所以檔案和資料儲存在資源中更方便訪問。

2. 凡是在R檔案中定義的資源都可以通過 “@Static_inner_classes_name/resourse_name”的方式獲取如:“@id/button”, @string/app_name。表示式:“@+id/button”,意思是在不久檔案中為一些元件新增id屬性。+表表示在R.java的名為id的內部類中新增一條記錄。

 

XML:是Internet環境中跨平臺的依賴於內容的技術,是當前處理結構化文件資訊的有力工具。使用一系列簡單的標記描述資料。(76)

SAX: 是一種以事件為驅動的XML API,由它定義的事件流可以指定從解析器傳到專門的處理程式程式碼的XML結構,簡單的講,它是個解析速度快,佔用記憶體少的解析器,這種技術特別適用於Android等移動裝置。

 

備註:以事件為驅動

簡單地說就是你點什麼按鈕(即產生什麼事件),電腦執行什麼操作(即呼叫什麼函式).當然事件不僅限於使用者的操作. 事件驅動的核心自然是事件。從事件角度說,事件驅動程式的基本結構是由一個事件收集器、一個事件傳送器和一個事件處理器組成。事件收集器專門負責收集所有事件,包括來自使用者的(如滑鼠、鍵盤事件等)、來自硬體的(如時鐘事件等)和來自軟體的(如作業系統、應用程式本身等)。事件傳送器負責將收集器收集到的事件分發到目標物件中。事件處理器做具體的事件響應工作,它往往要到實現階段才完全確定,因而需要運用虛擬函式機制(函式名往往取為類似於HandleMsg的一個名字)。對於框架的使用者來說,他們唯一能夠看到的是事件處理器。這也是他們所關心的內容。

 

DEMO:使用SAX解析XML文件:

1.建立一個Person類,存放相關的資訊:

package com.example.model;

public class Person {
private Integer id;
private String name;
private Short age;

public Person() {
// TODO Auto-generated constructor stub
}


public Person(Integer id, String name, Short age) {
super();
this.id = id;
this.name = name;
this.age = age;
}


public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Short getAge() {
return age;
}

public void setAge(Short age) {
this.age = age;
}

@Override
public String toString() {
// TODO Auto-generated method stub
return "id=" +id +",name="+name+",age=" + age;
}

}

2.建立一個SAXForHandler類,繼承自DefaultHandler,DefaultHandler實現了ContentHandler,ContentHandler提供了相應的方法。

package com.example;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.util.Log;

import com.example.model.Person;

public class SAXForHandler extends DefaultHandler {
private static final String TAG = "SAXForHandler";
private List<Person> persons;
private String perTag; // record the name of previous tag
Person person;// current person

public List<Person> getPersons() {
return persons;
}

/**
* 在開始解析文件時執行一次
*/
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
persons = new ArrayList<Person>();
Log.i(TAG, "****startDocument()****");
}

@Override
public void endDocument() throws SAXException {
Log.i(TAG, "****endDocument()****");
}

/**
* uri:名稱空間
* localName:標籤名稱
* qName:帶 名稱空間的標籤名
* attributes:存放該標籤的所有屬性
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if ("person".equals(localName)) {
for (int i = 0; i < attributes.getLength(); i++) {
Log.i(TAG, "attributeName:" + attributes.getLocalName(i) + ",attribute_value" +attributes.getValue(i) );
person = new Person();
person.setId(Integer.valueOf(attributes.getValue(i)));
}
}
perTag = localName;
Log.i(TAG, qName + "****startElement()****" );

}

@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
Log.i(TAG, "qName" + "***endElement()***");
if("person".equals(localName)){
persons.add(person);
person =null;
}
perTag = null;
}

/**
* ch:當前讀取到的TextNode節點
* start:位元組開始的位置,如果要讀取全部,那就是從0開始
* length:當前TextNode的長度
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String data = new String(ch,start,length).trim();
if(!"".equals(data)){
Log.i(TAG, "content" + data);
}
if("name".equals(perTag)){
person.setName(data);
}else if("age".equals(perTag)){
person.setAge(new Short(data));
}
}

}

 

3.建立一個person.xml檔案放在src下:

<?xml version="1.0" encoding="utf-8"?>
<persons>
<person id="1">
<name>wyy</name>
<age>27</age>
</person>
<person id="2">
<name>cL</name>
<age>26</age>
</person>
</persons>

4.測試的activity:

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
List<Person> ps = sax_XML();
for (int i = 0; i <ps.size(); i++) {
Person p = ps.get(i);
Log.i("AA", p.getName() +"id="+p.getId()+",age="+p.getId() );
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

public List<Person> sax_XML() throws Exception{
//通過類載入器獲取路徑,再以輸入流的方式放入解析器。
InputStream is = MainActivity.class.getClassLoader().getResourceAsStream("wangyuanyuan.xml");

SAXForHandler handler = new SAXForHandler();
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser();
//使用SAXParser
// saxParser.parse(is, handler);
//使用xmlReader
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setContentHandler(handler);
xmlReader.parse(new InputSource(is));
List<Person> list = handler.getPersons();
is.close();
return list;
}

}

 

兩種方法使用SAXParser 和xmlReader都可以解析成功。

 

除了使用SAX我們還可以使用DOM、PULL等解析XML文件。其中PULL解析器被整合在了android系統中 。PULL解析器不僅僅可以解析XML還可以修改或者生成新的XML檔案

 

 


不過最近在我們的專案中一般都是用json解析,更加簡潔方便。

 

 

參考:百度百科、《Android 4.0 網路程式設計》

 

相關文章