SAX解析XML原理
- SAX是以事件驱动,扫描开始和结束标签,来触发相应事件的进行。
- SAX,它既是一个接口,也是一个软件包.但作为接口,SAX是事件驱动型XML解析的一个标准接口不会改变 SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
大多数SAX都会产生以下类型的事件:
1.在文档的开始和结束时触发文档处理事件。
2.在文档内每一XML元素接受解析的前后触发元素事件。
3.任何元数据通常由单独的事件处理
4.在处理文档的DTD或Schema时产生DTD或Schema事件。
5.产生错误事件用来通知主机应用程序解析错误。
代码演示
-
文档目录结构
-
XML文件
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student id="01">
<name>张三</name>
<age>20</age>
<brithday>1996-03-04</brithday>
</student>
<student id="02">
<name>李四</name>
<age>28</age>
<brithday>1993-03-01</brithday>
</student>
</students>
- 实体类
package xml;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Student {
private int id;
private String name;
private int age;
private Date brithday;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBrithday() {
return brithday;
}
public void setBrithday(Date brithday) {
this.brithday = brithday;
}
@Override
public String toString() {
SimpleDateFormat sp = new SimpleDateFormat("yyyy-mm-dd");
String day = sp.format(brithday);
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", brithday=" + day + "]";
}
}
- 解析方法
package xml;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.Attributes.Name;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXPraseXML extends DefaultHandler{
private List<Student> list;
private String tagName;
private Student student;
public List<Student> getStudent() {
return list;
}
//开始解析XML文档
@Override
public void startDocument() throws SAXException {
list = new ArrayList<>();
}
//解析XML文档结束
@Override
public void endDocument() throws SAXException {
System.out.println("解析文档结束...");
}
//开始解析xml每个子元素(需要多次调用执行)
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals("student")) {
student = new Student();
//获取student中的id
int id = Integer.parseInt(attributes.getValue(0));
student.setId(id);
}
this.tagName = qName;
}
//在startElement和endElement之间调用多次
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
//去除每个节点前后空格
String str=new String(ch,start,length).trim();
//如果开始解析文档,则tagName不为空
if (this.tagName!=null) {
if (this.tagName.equals("name")) {
student.setName(str);
}
if (this.tagName.equals("age")) {
student.setAge(Integer.parseInt(str));
}
if (this.tagName.equals("brithday")) {
SimpleDateFormat sp = new SimpleDateFormat("yyyy-mm-dd");
try {
student.setBrithday(sp.parse(str));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//结束解析xml每个子元素(需要多次调用执行)
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals("student")) {
list.add(student);
}
this.tagName = null;
}
}
- 测试类
package xml;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
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 Test {
public static void main(String[] args) throws Exception {
//固定写法,利用工厂生成sax转换对象
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
//获取文件输入流
InputStream in = Test.class.getClassLoader().getResourceAsStream("xml/students.xml");
//实例化自写方法,实现xml转换为list对象的存储位置
SAXPraseXML saxPraseXML = new SAXPraseXML();
//利用转换方法将xml文件的输入流in,解析成list对象存储在saxPraseXML中
parser.parse(in, saxPraseXML);
//循环遍历对象,打印输出
List<Student> students = saxPraseXML.getStudent();
for(Student stu:students) {
System.out.println(stu);
}
}
}
- 测试结果
解析文档结束...
Student [id=1, name=张三, age=20, brithday=1996-03-04]
Student [id=2, name=李四, age=28, brithday=1993-03-01]