引入SAX
相当于DOM解析来说,DOM一次会将所有的内容全部加载到内存中然后去解析内容到集合中去查找,如果对于较大的XML文件,则会非常影响内存的使用,同时对于大文件DOM解析效率非常低。所以引入SAX(流读取的机制)解析的方法。
SAX基本概念
流读取的机制是只负责读取,不进行存储,但是会给出一定的关键的事件,提示你进行相应的保存操作。流机制(SAX)是引导你进行提取自己关注的信息(私人订制)。就个人的理解而言非常类似于顺序查找,找到符合要求的存入list,不符合的直接跳过,依次从头开始查找。
SAX提供了哪些回调事件:
当读到文档开始处触发事件:startDocument
当读到文档结束处触发事件:endDocument
当读到元素开始处触发事件:startElement
当读到元素结束处触发事件:endElement
读到内容时触发事件:characters
一个简单的例子说明一切(不懂的看注释)
1、在本地F://zztest/xiyouji.xml的位置定义一个xml文件
<?xml version="1.0" encoding="GB2312"?>
<bookstore>
<book category="COOKING">
<title lang="en">西游记</title>
<author>吴承恩</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="COOKING">
<title lang="en">水浒传</title>
<author>施耐庵</author>
<year>2003</year>
<price>29.00</price>
</book>
</bookstore>
2、定义一个继承DefaultHandler类的Handler类
package saxdemo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class Myhandler extends DefaultHandler {
//该map相当于一个中间变量
private Map<String, String> map;
//list用于接收要检索标签的全部内容
private ArrayList<Map<String, String>> list;
//当前检索的标签名
private String currentTag;
//当前检索标签名对应的值
private String currentValue;
//要检索的标签名
private String nodeName;
public Myhandler() {
}
public Myhandler(String name) {
this.nodeName = name;
}
public ArrayList<Map<String, String>> getList() {
return this.list;
}
@Override
public void startDocument() throws SAXException {
System.out.println("******start document******");
list = new ArrayList<Map<String, String>>();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.println("******start element******");
// qName为当前的标签名,nodeName为要检索的标签名,外部通过构造方法传入
if (qName.equals(nodeName)) {
map = new HashMap<String, String>();
}
// 当前的节点存在属性列表 && 当前的标签名和要检索的标签名一致
if (attributes != null && map != null) {
// 循环获取所有的属性名和对应的值放到map中
for (int i = 0; i < attributes.getLength(); i++) {
map.put(attributes.getQName(i), attributes.getValue(i));
}
}
// 正在解析的元素
currentTag = qName;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.println("******characters******");
// currentTag为当前检索的标签名,currnetValue为currentTag标签名对应的值
if (currentTag != null && map != null) {
//ch为当前检索的标签名对应的值,即刚好赋值给currentValue
currentValue = new String(ch, start, length);
if (currentValue != null && !currentValue.trim().equals("") && !currentValue.trim().equals("\n")) {
map.put(currentTag, currentValue);
System.out.println("-----" + currentTag + " " + currentValue);
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("******end element******");
//element结束的时候向list中添加内容
if (qName == nodeName) {
list.add(map);
}
}
@Override
public void endDocument() throws SAXException {
System.out.println("******end document******");
super.endDocument();
}
}
3、定义测试类
package saxdemo;
import java.io.File;
import java.util.ArrayList;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class SaxDemo {
public static void main(String[] args) {
File file = new File("F:" + File.separator + "zztest" + File.separator + "xiyouji.xml");
ArrayList<Map<String, String>> list = readXML(file, "bookstore");
System.out.println(list);
}
private static ArrayList<Map<String, String>> readXML(File file, String string) {
Myhandler myhandler = new Myhandler("book");
try {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
saxParser.parse(file, myhandler);
return myhandler.getList();
} catch (Exception e) {
}
return null;
}
}
测试结果:
******start document******
******start element******
******characters******
******start element******
******characters******
******start element******
******characters******
-----title 西游记
******end element******
******characters******
******start element******
******characters******
-----author 吴承恩
******end element******
******characters******
******start element******
******characters******
-----year 2005
******end element******
******characters******
******start element******
******characters******
-----price 30.00
******end element******
******characters******
******end element******
******characters******
******start element******
******characters******
******start element******
******characters******
-----title 水浒传
******end element******
******characters******
******start element******
******characters******
-----author 施耐庵
******end element******
******characters******
******start element******
******characters******
-----year 2003
******end element******
******characters******
******start element******
******characters******
-----price 29.00
******end element******
******characters******
******end element******
******characters******
******end element******
******end document******
[{year=2005, author=吴承恩, price=30.00, category=COOKING, lang=en, title=西游记}, {year=2003, author=施耐庵, price=29.00, category=COOKING, lang=en, title=水浒传}]
结果翻译: 前部分带*的部分可以看出SAX的解析过程是顺序的,最后一行为检索到的结果。