SAX解析是XML解析的常用方式之一,属于事件驱动的流式解析模式,解析过程中会逐行扫描XML文档,遇到对应节点或内容时触发回调事件,开发者可以通过重写事件处理器的方法捕获文档中的所有信息,最终拼接输出完整的文档内容。这种方式不需要将整个文档加载到内存,适合处理体积较大的XML文件,内存占用远低于DOM解析。

SAX解析核心原理
SAX解析的核心是通过SAXParser解析器读取XML文档,同时绑定自定义的DefaultHandler事件处理器,解析器在扫描文档时会触发以下关键事件:
- 文档开始解析时触发
startDocument方法 - 遇到元素开始标签时触发
startElement方法 - 遇到元素文本内容时触发
characters方法 - 遇到元素结束标签时触发
endElement方法 - 文档解析完成时触发
endDocument方法
我们只需要在这些方法中捕获对应的内容,就可以拼接出完整的XML文档内容。
准备测试用contact.xml文件
首先准备需要解析的contact.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<contactList>
<contact id="1">
<name>张三</name>
<phone>13800138000</phone>
<email>zhangsan@ipipp.com</email>
</contact>
<contact id="2">
<name>李四</name>
<phone>13900139000</phone>
<email>lisi@ipipp.com</email>
</contact>
</contactList>自定义SAX事件处理器
我们需要继承DefaultHandler类,重写对应的事件方法,用一个StringBuilder对象拼接所有的文档内容:
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.lang.StringBuilder;
public class ContactSaxHandler extends DefaultHandler {
// 用于存储完整文档内容的容器
private StringBuilder xmlContent = new StringBuilder();
// 用于临时存储文本内容的缓冲区
private char[] tempChars;
@Override
public void startDocument() throws SAXException {
// 文档开始解析,可在此处添加XML声明(部分解析器不会自动触发声明回调,需手动拼接)
xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 拼接元素开始标签
xmlContent.append("<").append(qName);
// 拼接元素的所有属性
for (int i = 0; i < attributes.getLength(); i++) {
String attrName = attributes.getQName(i);
String attrValue = attributes.getValue(i);
xmlContent.append(" ").append(attrName).append("=\"").append(attrValue).append("\"");
}
xmlContent.append(">");
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// 存储字符内容到临时缓冲区
tempChars = new char[length];
System.arraycopy(ch, start, tempChars, 0, length);
// 将文本内容拼接到结果中
xmlContent.append(new String(tempChars));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// 拼接元素结束标签
xmlContent.append("</").append(qName).append(">");
}
@Override
public void endDocument() throws SAXException {
// 文档解析完成,可在此处做最终处理
System.out.println("XML文档解析完成");
}
// 对外提供获取完整文档内容的方法
public String getXmlContent() {
return xmlContent.toString();
}
}编写主程序执行解析
通过SAXParserFactory创建解析器,绑定自定义处理器,执行解析并输出完整内容:
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
public class SAXParseDemo {
public static void main(String[] args) {
try {
// 创建SAX解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
// 获取SAX解析器实例
SAXParser parser = factory.newSAXParser();
// 创建自定义事件处理器
ContactSaxHandler handler = new ContactSaxHandler();
// 指定要解析的contact.xml文件路径,替换为实际文件存放路径
File xmlFile = new File("contact.xml");
// 执行解析,传入文件和处理器
parser.parse(xmlFile, handler);
// 获取并输出完整的XML文档内容
String fullContent = handler.getXmlContent();
System.out.println("完整XML文档内容:\n" + fullContent);
} catch (Exception e) {
e.printStackTrace();
}
}
}解析结果说明
运行上述程序后,控制台会输出contact.xml的完整内容,和原始文件内容一致。需要注意的是,如果XML文件中的文本内容包含换行或空格,characters方法可能会被多次调用,上述代码通过临时缓冲区存储字符内容,避免内容拼接错误。如果需要更精准的格式控制,可以在startElement和endElement方法中根据需要添加换行符,匹配原始XML的缩进格式。
SAX解析XMLcontact.xmlJava修改时间:2026-06-03 14:54:23