SAX解析是XML解析的一种常用方式,它基于事件驱动模型,在解析XML文档时不会将整个文档加载到内存中,而是逐行读取并触发对应的事件回调,适合处理体积较大的XML文件,内存占用低,解析效率较高。本文将以Java语言为例,详细讲解SAX解析的完整过程和代码实现。

SAX解析核心原理
SAX解析的核心是通过XMLReader读取XML文档,同时注册一个继承自DefaultHandler的事件处理器,当解析器遇到XML的不同节点时,会自动调用处理器中对应的回调方法,开发者只需要在这些方法中编写处理逻辑即可。
整个解析过程会依次触发以下事件:文档开始、元素开始、元素文本内容、元素结束、文档结束,对应的回调方法分别是startDocument、startElement、characters、endElement、endDocument。
SAX解析代码实现步骤
1. 准备待解析的XML文件
首先创建一个简单的XML文件,内容如下,后续解析会基于这个文件展开:
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user id="1">
<name>张三</name>
<age>25</age>
<email>zhangsan@ipipp.com</email>
</user>
<user id="2">
<name>李四</name>
<age>28</age>
<email>lisi@ipipp.com</email>
</user>
</users>2. 自定义事件处理器
创建继承自DefaultHandler的类,重写需要的事件回调方法,这里我们需要处理元素开始、文本内容和元素结束事件:
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
public class UserSAXHandler extends DefaultHandler {
// 存储解析出的用户列表
private List<User> userList = new ArrayList<>();
// 临时存储当前解析的用户对象
private User currentUser;
// 临时存储当前解析的元素名称
private String currentElement;
// 文档开始解析时调用
@Override
public void startDocument() throws SAXException {
System.out.println("开始解析XML文档");
}
// 遇到元素开始时调用
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
currentElement = qName;
if ("user".equals(qName)) {
// 遇到user元素,创建新的用户对象
currentUser = new User();
// 获取id属性
String id = attributes.getValue("id");
if (id != null) {
currentUser.setId(Integer.parseInt(id));
}
}
}
// 遇到元素文本内容时调用
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (currentUser == null) {
return;
}
String text = new String(ch, start, length).trim();
if (text.length() == 0) {
return;
}
// 根据当前元素名称赋值
if ("name".equals(currentElement)) {
currentUser.setName(text);
} else if ("age".equals(currentElement)) {
currentUser.setAge(Integer.parseInt(text));
} else if ("email".equals(currentElement)) {
currentUser.setEmail(text);
}
}
// 遇到元素结束时调用
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("user".equals(qName)) {
// user元素结束,将当前用户加入列表
userList.add(currentUser);
currentUser = null;
}
currentElement = null;
}
// 文档解析结束时调用
@Override
public void endDocument() throws SAXException {
System.out.println("XML文档解析结束");
}
// 获取解析结果
public List<User> getUserList() {
return userList;
}
}3. 创建用户实体类
为了存储解析后的用户数据,需要创建对应的实体类:
public class User {
private int id;
private String name;
private int age;
private String email;
// getter和setter方法
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "', age=" + age + ", email='" + email + "'}";
}
}4. 编写解析入口代码
使用SAXParserFactory创建解析器,关联事件处理器并执行解析:
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.util.List;
public class SAXParseDemo {
public static void main(String[] args) {
try {
// 创建SAX解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
// 创建SAX解析器
SAXParser saxParser = factory.newSAXParser();
// 创建自定义事件处理器
UserSAXHandler handler = new UserSAXHandler();
// 执行解析,传入XML文件路径和处理器
saxParser.parse(new File("users.xml"), handler);
// 获取解析结果
List<User> userList = handler.getUserList();
// 输出解析结果
for (User user : userList) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}SAX解析注意事项
characters方法可能会被多次调用,比如文本内容中存在换行或者特殊字符时,需要将多次获取的内容拼接后再处理,本文示例中做了trim处理,实际开发可以根据需求调整。- 元素结束后要及时清空当前元素的临时变量,避免影响下一个同类型元素的解析。
- 如果XML文件包含命名空间,需要在创建解析器工厂时调用
factory.setNamespaceAware(true)开启命名空间支持。 - SAX解析是只读的,只能顺序解析XML内容,无法修改XML文档结构,如果需要修改XML内容,可以选择DOM解析方式。
以上就是SAX解析的完整过程和代码实现,开发者可以根据自己的需求调整事件处理器中的逻辑,处理不同结构的XML文档。
XML解析SAX解析Java_SAXXMLReaderDefaultHandler修改时间:2026-06-03 14:50:08