一、简介
在上篇文章中,我们介绍了 DOM 解析技术!
经过整理,通过 Java 程序解析 XML 文件,目前比较主流的有以下四种方式:
- DOM 解析
- SAX 解析
- JDOM 解析
- DOM4J 解析
本篇介绍第二种解析技术:SAX 解析!
三、SAX 解析
SAX 的全称是:Simple API for XML,也是 JDK 提供的另一种 XML 解析方式。
相比于 DOM,SAX 每次解析只在内存中加载 XML 文件的一小部分,即使针对较大的 XML 文件,它也不需要占用太多的内存,也不会存在内存溢出的问题。
优点如下:
- 1.采用事件驱动模式一段一段的来解析数据,占用内存小
- 2.只在读取数据时检查数据,不需要保存在内存中
- 3.效率和性能较高,能解析大于系统内存的文档
当然也有缺点:
- 1.与 DOM 解析器相比,使用 SAX 解析器读取 XML 文件时,解析逻辑比较复杂
- 2.同时无法定位文档层次,很难同时访问同一文档的不同部分数据,不支持 XPath
下面我们以如下的 XML 文件为例,介绍解析的实现过程。
<?xml version="1.0" encoding="utf-8" ?>
<class>
<student id="1">
<name>张三</name>
<gender>男</gender>
<age>26</age>
</student>
<student id="2">
<name>里斯</name>
<gender>男</gender>
<age>36</age>
</student>
<student id="3">
<name>王五</name>
<gender>女</gender>
<age>24</age>
</student>
</class>
SAX 解析,实现过程如下:
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
public class SAXDemo {
public static void main(String[] args) throws Exception {
// 1.获取xml文件流
InputStream inputStream = SAXDemo.class.getClassLoader().getResourceAsStream("demo.xml");
// 2.获取SAXParserFactory实例
SAXParserFactory factory = SAXParserFactory.newInstance();
// 3.获取SAXparser实例
SAXParser saxParser = factory.newSAXParser();
// 4.创建Handel对象
SAXDemoHandel handel = new SAXDemoHandel();
// 5.解析XML文件
saxParser.parse(inputStream, handel);
// 6.获取读取结果
List<Map<String, String>> students = handel.getStudents();
for (Map<String, String> student : students) {
System.out.println(student.toString());
}
}
}
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SAXDemoHandel extends DefaultHandler {
private String value;
private Map<String, String> student;
private List<Map<String, String>> students = new ArrayList<>();
public List<Map<String, String>> getStudents() {
return students;
}
/**
* xml 解析开始
* @throws SAXException
*/
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("xml 解析开始");
}
/**
* xml 解析结束
* @throws SAXException
*/
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("xml 解析结束");
}
/**
* 解析 XML 元素开始
* @param uri
* @param localName
* @param qName
* @param attributes
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
System.out.println("开始遍历节点:" + qName);
if (qName.equals("student")){
student = new HashMap<>();
for(int i=0; i<attributes.getLength();i++){
student.put(attributes.getQName(i), attributes.getValue(i));
}
}
}
/**
* 解析 XML 元素结束
* @param uri
* @param localName
* @param qName
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
System.out.println("节点遍历结束:" + qName);
if(qName.equals("student")){
students.add(student);
student = null;
} else if(qName.equals("name") || qName.equals("gender") || qName.equals("age")){
student.put(qName, value);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
// 获取节点值数组
value = new String(ch,start,length).trim();
if (!value.equals("")) {
System.out.println(value);
}
}
}
运行结果如下:
{gender=男, name=张三, id=1}
{gender=男, name=里斯, id=2}
{gender=女, name=王五, id=3}
三、小结论
相比于 DOM,SAX 每次解析只在内存中加载 XML 文件的一小部分,即使针对较大的 XML 文件,它也不需要占用太多的内存,也不会存在内存溢出的问题。
写到最后
不会有人刷到这里还想白嫖吧?点赞对我真的非常重要!在线求赞。加个关注我会非常感激!