<一>簡介
什麼是SAX呢?以前只是聽說SAX,SAX的,但從未接觸,今天學習一下,順便做一下筆記。
SAX是Simple API for XML的縮寫,它既是一個接口也是一個包。
SAX是一個解析速度快並且占用內存少的xml解析器,非常適合用於Android等移動設備。 這個不同於DOM解析,DOM是把全部數據放入內存進行解析。
SAX解析XML文件采用的是事件驅動,也就是說,它並不需要解析完整個文檔。在按內容順序解析文檔的過程中,SAX會判斷當前讀到的字符是否合法XML語法中的某部分,如果符合就會觸發事件。所謂事件,其實就是一些回調方法,這些方法定義在ContentHandler接口中。
另外一點就是:SAX在解析件的過程中得到自己需要的信息後可以隨時終止解析,並不一定要等文件全部解析完畢。
有優勢必定優劣勢:SAX采用的是流式處理方式,當遇到某個標簽的時候,它並不會記錄下以前所遇到的標簽,也就是說,在處理某個標簽的時候,比如在startElement方法中,所能夠得到的信息就是標簽的名字和屬性,至於標簽內部的嵌套結構,上層標簽、下層標簽以及其兄弟節點的名稱等等與其結構相關的信息都是不得而知的。實際上就是把XML文件的結構信息丟掉了,如果需要得到這些信息的話,只能你自己在程序裡進行處理了。所以相對DOM而言,SAX處理XML文檔沒有DOM方便,SAX處理的過程相對DOM而言也比較復雜。
<二>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文件中讀到的內容。例如:<name>xiaosi</name> 主要目的是獲取name標簽中的值。
第一個參數用於存放文件的內容,後面兩個參數是讀到的字符串在這個數組中的起始位置和長度,使用new String(ch,start,length)就可以獲取內容。
<?xml version="1.0"?> ---------->startDocument()
<student> ---------->startElement
<name> ---------->startElement
xiasoi ---------->characters
</name> ---------->endElement
<id> ---------->startElement
090105 ---------->characters
</id> ---------->endElement
</student> --------->endElement
文檔結束 --------->startDocument()
<三>解析步驟
使用SAX解析XML文件一般有以下五個步驟:
1、創建一個SAXParserFactory對象(通過類名很容易得知它利用工廠方法模式實現的);
2、調用SAXParserFactory中的newSAXParser方法創建一個SAXParser對象;
3、然後在調用SAXParser中的getXMLReader方法獲取一個XMLReader對象;
4、在XMLReader中注冊事件處理接口,一般有ContentHandler、ErrorHandler、DTDHandler、EntityHandler四種;
5、調用XMLReader中的parse方法解析指定的XML字符串對象;
具體實現:
注意:因為ContentHandler是一個接口,在使用的時候有些不方便,需要全部實現所有的方法,但是有些方法我們會用不到。因此,SAX還為其制定了一個Helper類:DefaultHandler,它實現了這個接口,但是其所有的方法體都為空,在實現的時候,你只需要繼承這個類,然後重載相應的方法即可
[java]
package xiaosi.sax;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class XMLSAXActivity extends Activity
{
private Button button = null;
private String xmlContent = "";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v)
{
try
{
getWeatherArray("beijing");
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
XMLReader xmlReader = saxFactory.newSAXParser().getXMLReader();
xmlReader.setContentHandler(new MyContentHandler());
String xml= "<student><name>xiaosi</name><id>090105</id></student>";
xmlReader.parse(new InputSource(new StringReader(xml)));
}
catch (SAXException e)
{
e.printStackTrace();
}
catch (ParserConfigurationException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
}
MyContentHandler:
[java]
package xiaosi.sax;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
public class MyContentHandler extends DefaultHandler
{
String tag = "XIAOSI";
@Override
public void startDocument() throws SAXException
{
Log.i(tag, "startDocument");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
Log.i(tag, "startElement");
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException
{
Log.i(tag, "characters");
}
@Override
public void endDocument() throws SAXException
{
Log.i(tag, "endDocument");
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException
{
Log.i(tag, "endElement");
}
}