1.SAX是一個解析速度快並且占用內存少的xml解析器,非常適合用於Android等移動設備。
SAX解析XML文件采用的是事件驅動,也就是說,它並不需要解析完整個文檔,在按內容順
序解析文檔的過程中,SAX會判斷當前讀到的字符是否合法XML語法中的某部分,如果符合
就會觸發事件。所謂事件,其實就是一些回調(callback)方法,這些方法(事件)定義在
ContentHandler接口。下面是一些ContentHandler接口常用的方法:
startDocument()
當遇到文檔的開頭的時候,調用這個方法,可以在其中做一些預處理的工作。
endDocument()
和上面的方法相對應,當文檔結束的時候,調用這個方法,可以在其中做一些善後的工作
startElement(String namespaceURI, String localName, String qName, Attributes
atts)當讀到一個開始標簽的時候,會觸發這個方法。namespaceURI就是命名空間,
localName是不帶命名空間前綴的標簽名,qName是帶命名空間前綴的標簽名。通過atts可
以得到所有的屬性名和相應的值。要注意的是SAX中一個重要的特點就是它的流式處理,當
遇到一個標簽的時候,它並不會紀錄下以前所碰到的標簽,也就是說,在startElement()
方法中,所有你所知道的信息,就是標簽的名字和屬性,至於標簽的嵌套結構,上層標簽
的名字,是否有子元屬等等其它與結構相關的信息,都是不得而知的,都需要你的程序來
完成。這使得SAX在編程處理上沒有DOM來得那麼方便。endElement(String uri, String
localName, String name)這個方法和上面的方法相對應,在遇到結束標簽的時候,調用這
個方法。characters(char[] ch, int start, int length)
這個方法用來處理在XML文件中讀到的內容,第一個參數為文件的字符串內容,後面兩個參
數是讀到的字符串在這個數組中的起始位置和長度,使用ew String(ch,start,length)就
可以獲取內容。
--------------------------
使用sax解析xml
只要為SAX提供實現ContentHandler接口的類,那麼該類就可以得到通知事件(實際上就是
SAX調用了該類中的回調方法)。因為ContentHandler是一個接口,在使用的時候可能會有些
不方便,因此,SAX還為其制定了一個Helper類:DefaultHandler,它實現了ContentHandler
接口,但是其所有的方法體都為空,在實現的時候,你只需要繼承這個類,然後重寫相應的
方法即可。使用SAX解析itcast.xml的代碼如下:
public static List<Person> readXML(InputStream inStream) {
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser(); //創建解析器
//設置解析器的相關特性,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();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
SAX 支持已內置到JDK1.5中,你無需添加任何的jar文件。關於XMLContentHandler的代碼實
現請看本頁下面備注。
------------------------------------------------
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 cn.itcast.xml.domain.Person;
public class XMLContentHandler extends DefaultHandler {
private List<Person> persons = null;
private Person currentPerson;
private String tagName = null;//當前解析的元素標簽
public List<Person> getPersons() {
return persons;
}
/*
* 接收文檔的開始的通知。
*/
@Override public void startDocument() throws SAXException {
persons = new ArrayList<Person>();
}
/*
* 接收字符數據的通知。
*/
@Override public void characters(char[] ch, int start, int length) throws
SAXException {
if(tagName!=null){
String data = new String(ch, start, length);
if(tagName.equals("name")){
this.currentPerson.setName(data);
}else if(tagName.equals("age")){
this.currentPerson.setAge(Short.parseShort
(data));
}
}
}
/*
* 接收元素開始的通知。
* 參數意義如下:
* namespaceURI:元素的命名空間
* localName :元素的本地名稱(不帶前綴)
* qName :元素的限定名(帶前綴)
* atts :元素的屬性集合
*/
@Override public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
if(localName.equals("person")){
currentPerson = new Person();
currentPerson.setId(Integer.parseInt(atts.getValue
("id")));
}
this.tagName = localName;
}
/*
* 接收文檔的結尾的通知。
* 參數意義如下:
* uri :元素的命名空間
* localName :元素的本地名稱(不帶前綴)
* name :元素的限定名(帶前綴)
*
*/
@Override public void endElement(String uri, String localName, String
name) throws SAXException {
if(localName.equals("person")){
persons.add(currentPerson);
currentPerson = null;
}
this.tagName = null;
}
}
-----------------------------------------------------
public class Person {
private Integer id;
private String name;
private Short 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;
}
}
-------------------------------------------
使用sax解析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>
解析credream.xml觸發的事件為:
讀到的標簽及內容 觸發事件
{文檔開始} startDocument()
<persons> startElement(, "persons", null, "{Attributes}")
"\n\t" characters("<persons>...</persons>", "12", "2")
<person> startElement(, "person", null, "{Attributes}")
"\n\t\t" characters("<persons>...</persons>", "31", "3")
<name> startElement(, "name", null, "{Attributes}")
"李明" characters("<persons>...</persons>", "40", "2")
</name> endElement("", "name", null)
"\n\t\t" characters("<persons>...</persons>", "50", "3")
<age> startElement(, "age", null, "{Attributes}")
"30" characters("<persons>...</persons>", "58", "2")
</age> endElement("", "age", null) www.2cto.com
"\n\t" characters("<persons>...</persons>", "67", "2")
</person> endElement("", "person", null)
"\n\t" characters("<persons>...</persons>", "79", "2")
<person> startElement(, "person", null, "{Attributes}")
"\n\t\t" characters("<persons>...</persons>", "98", "3")
<name> startElement(, "name", null, "{Attributes}")
"李向梅" characters("<persons>...</persons>", "107", "3")
</name> endElement("", "name", null)
"\n\t\t" characters("<persons>...</persons>", "118", "3")
<age> startElement(, "age", null, "{Attributes}")
"25" characters("<persons>...</persons>", "126", "2")
</age> endElement("", "age", null)
"\n\t" characters("<persons>...</persons>", "135", "2")
</person> endElement("", "person", null)
"\n" characters("<persons>...</persons>", "147", "1")
</persons> endElement("", "persons", null)
{文檔結束} endDocument()