一、SAX解析原理简介
原理:SAX方式采用事件处理的方式解析XML文件,涉及到两个部分:解析器和事件处理器。
SAX解析器从XML文件第一行开始往下读,读取一行处理一行(
不能往回读取
)。解析器每读取一行将会触发特定的事件,然后调用事件处理器中处理该事件的方法。
解析器:可以使用Jaxp的API创建,创建SAX解析器后就可以指定它解析某个XML文件。
事件处理器:由程序员编写,程序员通过事件处理器中的方法的参数,就可以很轻松地得到SAX解析器解析到的数据,从而可以决定如果对数据进行处理。
解析过程:解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的某个一个部分,都会去调用事件处理器中的一个方法。解析器在调用事件处理器中的方法时,会把当前解析到的XML内容当作方法的参数传给事件处理器。
SAX解析方式优点:SAX解析方式占用内存少,解析速度快;缺点是:只适合做文档的读取,不适合做文档的增删查改。
二、解析步骤
如下图所示,事件处理器有下面四种,一般情况下就使用内容处理器:ContentHander
三、内容处理器的实现
1. 实现ContentHander接口
2. 继承DefaultHander类
DefaultHander实现了
ContentHander接口,我们自己写的类可以继承
DefaultHander覆盖需要用到的方法。
DefaultHander类似于适配器类,开发中用的最多的同样是覆盖
characters、startDocument、endDocument
三个方法。
例如:
public class SAXContemtHander extends DefaultHandler { @Override public void startElement(String uri,String localName,String qName,Attributes attributes) { //触发标签的开始事件调用此函数 //qName为标签的名字 //attributes为标签的属性的集合 //you can do something } @Override public void characters(char[] ch,int start,int length) { //触发标签的内容调用此函数 //String text = new String(ch,start,length); text表示解析的内容 //you can do something } @Override public void endElement(String uri,String qName) { //触发标签的结束事件调用此函数 //qName为标签的名字 //you can do something } }
四、代码实现
方法一:
//1. 创建解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //2. 得到解析器 SAXParser parser = factory.newSAXParser(); //3. 获取读取器 XMLReader reader = parser.getXMLReader(); //4. 设置事件处理器 reader.setContentHandler(内容处理器的对象); //5. 解析XML文档内容 reader.parse(pathString);方法二:
//1. 创建解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //2. 得到解析器 SAXParser parser = factory.newSAXParser(); //3. 解析XML文档 parser.parse(new File(xmlPathString,内容处理器的对象);
五、例子程序
本例子将XML文件中的数据解析成JavaBean对象,并把对象放到List容器中。
1. XML数据样本:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <学生信息> <学生 姓名="陈小宝" 学号="201207203" 学院="计算机"> <语文>90</语文> <数学>100</数学> <英语>90</英语> <艺术>92</艺术> <计算机>100</计算机> </学生> <学生信息>2. 内容处理器
package cn.liyin.jaxp; import com.liyin.Domain.Student; import java.util.LinkedList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * 继承DefaultHandler类,覆盖自己需要用到的事件处理方法 比实现ContentHander * 接口要好的多,ContentHander要实现全部的接口方法 * * 此类作用:将XML内容解析到保存JavaBean对象的List中 * * @author 忘川 */ public class SAXContemtHander extends DefaultHandler { private String currentTag = null; private Student student = null; private List list = new LinkedList(); public List getStudents() { return list; } @Override public void startElement(String uri,Attributes attributes) throws SAXException { currentTag = qName; if ("学生".equals(currentTag)) { student = new Student(); student.setName(attributes.getValue("姓名")); student.setStudentId(attributes.getValue("学号")); student.setAcademy(attributes.getValue("学院")); } } @Override public void characters(char[] ch,int length) throws SAXException { //技巧:调用常量字符串的equals方法与变量比较可以有效防止由于变量 //等于null从而引发的空指针异常问题 if ("语文".equals(currentTag)) { student.setChinese(Integer.parseInt(new String(ch,length))); } if ("数学".equals(currentTag)) { student.setMath(Integer.parseInt(new String(ch,length))); } if ("英语".equals(currentTag)) { student.setEnglish(Integer.parseInt(new String(ch,length))); } if ("艺术".equals(currentTag)) { student.setArt(Integer.parseInt(new String(ch,length))); } if ("计算机".equals(currentTag)) { student.setComputer(Integer.parseInt(new String(ch,length))); } } @Override public void endElement(String uri,String qName) throws SAXException { if ("学生".equals(qName)) { list.add(student); student = null; } currentTag = null; } }3. JavaBean模型
package com.liyin.Domain; /** * * @author 忘川 */ public class Student { private String name; private String studentId; private String academy; private int chinese; private int math; private int english; private int art; private int computer; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getStudentId() { return studentId; } public void setStudentId(String studentId) { this.studentId = studentId; } public String getAcademy() { return academy; } public void setAcademy(String academy) { this.academy = academy; } public int getChinese() { return chinese; } public void setChinese(int chinese) { this.chinese = chinese; } public int getMath() { return math; } public void setMath(int math) { this.math = math; } public int getEnglish() { return english; } public void setEnglish(int english) { this.english = english; } public int getArt() { return art; } public void setArt(int art) { this.art = art; } public int getComputer() { return computer; } public void setComputer(int computer) { this.computer = computer; } }4. Junit测试代码
@Test public void test() throws ParserConfigurationException,SAXException,IOException { //1. 创建解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //2. 得到解析器 SAXParser parser = factory.newSAXParser(); //3. 获取读取器 XMLReader reader = parser.getXMLReader(); //4. 设置事件处理器 SAXContemtHander hander = new SAXContemtHander(); reader.setContentHandler(hander); //5. 解析XML文档内容 reader.parse("./data/Students_XML.xml"); List list = hander.getStudents(); }