<一>简介
什么是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)