SAX (Simple API for XML)是以流的方式处理XML,以缓存的方式陆续读取XML文件,是基于事件驱动的XML解析方式。它允许在读取文档的时候,即对文档进行解析,而不必像DOM那样需把整个文档加载完成后才会进行解析。
优点:内存开销小,适合解析比较大的XML文件。
缺点:只支持读,不支持写,访问效率低,且只能顺序访问。
示例:
(1)需要解析的XML文件(person.xml)
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="0001">
<name>Smith</name>
<sex>male</sex>
<age>20</age>
</person>
<person id="0002">
<name>Tom</name>
<sex>male</sex>
<age>22</age>
</person>
<person id="0003">
<name>John</name>
<sex>female</sex>
<age>33</age>
</person>
</persons>
(2)VO对象
public class Person {
private String id;
private String name;
private String sex;
private int age;
//省略了Getter和Setter方法
}
(3)解析方法
package review.fileoper;
import java.io.File;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class SAXParseXMLTest {
public List<Person> saxParseXML(File file) throws ParserConfigurationException, SAXException, Exception{
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
PersonSaxHandler handler = new PersonSaxHandler();
parser.parse(file, handler);
return handler.getPersonList();
}
}
(4)定义事件处理器PersonSaxHandler,它继承自DefaultHandler,而我们一般覆写它的五种方法
package review.fileoper;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class PersonSaxHandler extends DefaultHandler{
private List<Person> personList = new ArrayList<Person>(); //保存解析得到的对象
private Person person = null;
private String preTag = null;//作用是记录解析时的上一个节点名称
public List<Person> getPersonList(){
return this.personList;
}
@Override
public void startDocument() throws SAXException {
System.out.println("----begin parse XML file----");
//接收文档开始的通知,可以在文档的开始采取特定的措施(如分配树的根节点或创建输出文件)
super.startDocument();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
preTag = qName; //将正在解析的节点名称赋给preTag
if("person".equals(qName)){
person = new Person();
// 获得属性名获得元素的属性值,此处也可以通过属性顺序attributes.getValue(index)来获取属性值
person.setId(attributes.getValue("id"));
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String cont = new String(ch,start,length);
if("name".equals(preTag)){
person.setName(cont);
}else if("sex".equals(preTag)){
person.setSex(cont);
}else if("age".equals(preTag)){
person.setAge(Integer.parseInt(cont));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("person".equals(qName)){
personList.add(person);
}
//表示该节点解析完了,防止遇到换行符等“空字符串”时会执行characters方法
preTag = null;
}
@Override
public void endDocument() throws SAXException {
System.out.println("-----end parse XML file-----");
//接收文档结束的通知,可以在文档的结束处采取特定的操作(如,结束树或关闭输出文件)
super.endDocument();
}
}