为解决DOM的问题,出现了SAX。SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;
SAX是Simple API for XML的缩写,它并不是由W3C官方所提出的标准,虽然如此,使用SAX的还是不少,几乎所有的XML解析器都会支持它。
与DOM比较而言,SAX是一种轻量型的方法。我们知道,在处理DOM的时候,我们需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上的每个Node对象。当文档比较
小的时候,这不会造成什么问题,但是一旦文档大起来,处理DOM就会变得相当费时费力。特别是其对于内存的需求,也将是成倍的增长,以至于在某些应用中使用DOM是一件很不划算的事(比如在applet中)。这时候,一个较好的替代解决方法就是SAX。
SAX在概念上与DOM完全不同。它不同于DOM的文档驱动,它是事件驱动的,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。所谓事件驱动,是指一种基于
回调(callback)机制的程序运行方法。SAX基于事件的解析,解析器在一次读取XML文件中根据读取的数据产生相应的事件,由应用程序实现相应的事件处理逻辑,即它是一种“推”的解析方式;这种解析方法速度快、占用内存少,但是它需要应用程序自己处理解析器的状态,实现起来会比较麻烦。
具体示例:
(1)xml文件内容:在工程跟目录下建立xml/data1.xml文件,内容如下:
(2)解析:
demo传送门:
https://github.com/215836017/ParseXML_java
https://github.com/215836017/ParserXML_android
注:上面Java的demo中用到的xml文件是当前目录下的xml/data1.xml文件。result.xml是生成的文件。data2.xml, data3.xml是用来比较解析时间的。
Android的demo中用到xml文件是存放在手机根目录下的data1.xml文件。
SAX是Simple API for XML的缩写,它并不是由W3C官方所提出的标准,虽然如此,使用SAX的还是不少,几乎所有的XML解析器都会支持它。
与DOM比较而言,SAX是一种轻量型的方法。我们知道,在处理DOM的时候,我们需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上的每个Node对象。当文档比较
小的时候,这不会造成什么问题,但是一旦文档大起来,处理DOM就会变得相当费时费力。特别是其对于内存的需求,也将是成倍的增长,以至于在某些应用中使用DOM是一件很不划算的事(比如在applet中)。这时候,一个较好的替代解决方法就是SAX。
SAX在概念上与DOM完全不同。它不同于DOM的文档驱动,它是事件驱动的,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。所谓事件驱动,是指一种基于
回调(callback)机制的程序运行方法。SAX基于事件的解析,解析器在一次读取XML文件中根据读取的数据产生相应的事件,由应用程序实现相应的事件处理逻辑,即它是一种“推”的解析方式;这种解析方法速度快、占用内存少,但是它需要应用程序自己处理解析器的状态,实现起来会比较麻烦。
具体示例:
(1)xml文件内容:在工程跟目录下建立xml/data1.xml文件,内容如下:
<students>
<student>
<name sex="man">小明</name>
<nickName>明明</nickName>
<age>20</age>
<address>北京</address>
</student>
<student>
<name sex="woman">小红</name>
<nickName>红红</nickName>
<age>20</age>
<address>上海</address>
</student>
<student>
<name sex="man">小亮</name>
<nickName>亮亮</nickName>
<age>30</age>
<address>广州</address>
</student>
<student-0>
<name sex="man">小亮-0</name>
<nickName>亮亮-0</nickName>
<age>200</age>
<address>广州-0</address>
</student-0>
</students>
(2)解析:
private void parseXml() {
long startTime = System.currentTimeMillis();
System.out.println("开始解析: " + startTime);
try {
InputStream is = new FileInputStream(xmlFile);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser newSAXParser = factory.newSAXParser();
MyHandler handler = new MyHandler();
// 将解析交给处理器
newSAXParser.parse(is, handler);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
long finishTime = System.currentTimeMillis();
long countTime = finishTime - startTime;
System.out.println("结束解析: " + finishTime + "\nSax解析耗时:" + countTime);
for (Bean1 student : datas) {
System.out.println(student.toString());
}
}
class MyHandler extends DefaultHandler {
// 用于存储读取的临时变量
private String tempString;
private Bean1 bean;
/**
* 解析到文档开始调用,一般做初始化操作
*
* @throws SAXException
*/
@Override
public void startDocument() throws SAXException {
super.startDocument();
}
/**
* 解析到文档末尾调用,一般做回收操作
*
* @throws SAXException
*/
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
/**
* 每读到一个元素就调用该方法
*
* @param uri
* @param localName
* @param qName
* @param attributes
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if (qName.equals("student")) {
bean = new Bean1();
} else if (qName.equals("name")) {
// 获取name里面的属性
bean.setSex(attributes.getValue("sex"));
}
super.startElement(uri, localName, qName, attributes);
}
/**
* 读到元素的结尾调用
*
* @param uri
* @param localName
* @param qName
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("student".equals(qName)) {
datas.add(bean);
}
if (qName.equals("name")) {
bean.setName(tempString);
} else if (qName.equals("nickName")) {
bean.setName(qName);
} else if (qName.equals("age")) {
bean.setAge(qName);
} else if (qName.equals("adress")) {
bean.setAddress(qName);
}
super.endElement(uri, localName, qName);
}
/**
* 读到属性内容调用
*
* @param ch
* @param start
* @param length
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
tempString = new String(ch, start, length);
super.characters(ch, start, length);
}
}
demo传送门:
https://github.com/215836017/ParseXML_java
https://github.com/215836017/ParserXML_android
注:上面Java的demo中用到的xml文件是当前目录下的xml/data1.xml文件。result.xml是生成的文件。data2.xml, data3.xml是用来比较解析时间的。
Android的demo中用到xml文件是存放在手机根目录下的data1.xml文件。