解析XML文件的基本的解析方式有两种,一种叫SAX,另一种叫DOM:
1.DOM生成和解析XML文档
为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构。优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。
2.SAX生成和解析XML文档
为解决DOM的问题,出现了SAX。SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;
SAX全称Simple API for XML,既是指一种接口,也是指一个软件包。同时SAX是事件驱动型XML解析的一个标准接口。
SAX的工作原理是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续扫描,直到文档结束。
大部分SAX实现都会产生以下类型的事件:
1、文档开始和结束时触发文档处理事件;
2、在文档内每一xml元素解析前后触发元素事件;
3、任何元数据通常都由单独的事件交付;
4、在处理文档的DTD或者Schema时产生DTD或者Schema事件;
5、产生错误事件用来通知主机应用程序解析错误;
SAX模型:
对于12<doc>3<a>4hello!5</a>6</doc>7总共产生七个事件(数字代表事件的标号);
(1)创建事件处理程序;
(2)创建SAX解析器;
(3)将事件处理程序分配给解析器;
(4)对文档进行解析,将事件发送给处理程序;
ContentHandler接口是java类包中一个特殊的SAX接口,其中常用的接口有5个:
startDocument():Receive notification of the beginning of a document.
endDocument():Receive notification of the end of a document.
startElement(String uri, String localName, String qName, Attributes atts)
Receive notification of the beginning of an element.
endElement(String uri, String localName, String qName):Receive notification of the end of an element.
characters(char[] ch, int start, int length):Receive notification of character data.
下面是一个简单的例子:
Activity类:
public class XmlParserActivity extends Activity {
private Button parse;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
parse = (Button)findViewById(R.id.parse);
parse.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String xml="<school id='001'><stu><name>gap</name><sex>male</sex><age>23</age></stu></school>";
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
XMLReader reader = factory.newSAXParser().getXMLReader();
//为XMLReader设置内容处理器
reader.setContentHandler(new XMLContentHandler());
//开始处理xml,并且调用相应的事件响应函数
reader.parse(new InputSource(new StringReader(xml)));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
XMLContentHandler类:
public class XMLContentHandler extends DefaultHandler {
String tagName, name, sex, age;
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (tagName.equals("name"))
name = new String(ch, start, length);
else if(tagName.equals("sex"))
sex = new String(ch, start, length);
else if(tagName.equals("age"))
age = new String(ch, start, length);
}
@Override
public void endDocument() throws SAXException {
System.out.println("end document:");
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (localName.equals("school")) {
System.out.println("name--->" + name);
System.out.println("sex--->" + sex);
System.out.println("age--->" + age);
}
}
@Override
public void startDocument() throws SAXException {
System.out.println("start document:");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
tagName = localName;
if (tagName.equals("stu"))
for (int i = 0; i < attributes.getLength(); i++) {
System.out.println(attributes.getLocalName(i)+ " = " + attributes.getValue(i));
}
}
}
上面继承的是defaultHandler而不是contentHandler,这是一种适配器模式,因为contentHandler中有很多的方法不用实现。