JAXP是Java平台自带的处理XML的标准API,不需要额外引入第三方依赖,支持DOM和SAX两种主流的XML解析方式,适用于不同的业务场景。DOM解析会将整个XML文档加载到内存中,形成树形结构,适合需要频繁修改文档内容的场景;SAX解析是事件驱动的流式解析,不会将整个文档加载到内存,适合处理大体积的XML文件。

JAXP的DOM解析案例
首先准备一个待解析的XML文件,命名为user.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>接下来编写DOM解析的代码,实现读取所有用户信息的功能:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.io.File;
public class JAXPDOMParseDemo {
public static void main(String[] args) throws Exception {
// 1. 创建DocumentBuilderFactory实例
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2. 创建DocumentBuilder实例
DocumentBuilder builder = factory.newDocumentBuilder();
// 3. 解析XML文件,得到Document对象
Document document = builder.parse(new File("user.xml"));
// 4. 获取所有user节点
NodeList userNodes = document.getElementsByTagName("user");
// 5. 遍历user节点,读取内容
for (int i = 0; i < userNodes.getLength(); i++) {
Element userElement = (Element) userNodes.item(i);
// 获取id属性
String id = userElement.getAttribute("id");
// 获取name子节点内容
String name = userElement.getElementsByTagName("name").item(0).getTextContent();
// 获取age子节点内容
String age = userElement.getElementsByTagName("age").item(0).getTextContent();
// 获取email子节点内容
String email = userElement.getElementsByTagName("email").item(0).getTextContent();
System.out.println("用户ID:" + id + ",姓名:" + name + ",年龄:" + age + ",邮箱:" + email);
}
}
}JAXP的SAX解析案例
SAX解析需要实现DefaultHandler类中的回调方法,当解析器遇到不同的XML事件时会触发对应的方法。下面是使用SAX解析上述user.xml文件的代码:
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
public class JAXPSAXParseDemo {
public static void main(String[] args) throws Exception {
// 1. 创建SAXParserFactory实例
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2. 创建SAXParser实例
SAXParser parser = factory.newSAXParser();
// 3. 创建自定义Handler实例
UserHandler handler = new UserHandler();
// 4. 开始解析
parser.parse(new File("user.xml"), handler);
}
// 自定义Handler类,继承DefaultHandler
static class UserHandler extends DefaultHandler {
private String currentElement;
private String currentId;
private String currentName;
private String currentAge;
private String currentEmail;
// 遇到元素开始标签时触发
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
currentElement = qName;
if ("user".equals(qName)) {
currentId = attributes.getValue("id");
// 初始化当前用户的其他属性
currentName = "";
currentAge = "";
currentEmail = "";
}
}
// 遇到元素内容时触发
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String content = new String(ch, start, length).trim();
if (!content.isEmpty()) {
if ("name".equals(currentElement)) {
currentName = content;
} else if ("age".equals(currentElement)) {
currentAge = content;
} else if ("email".equals(currentElement)) {
currentEmail = content;
}
}
}
// 遇到元素结束标签时触发
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("user".equals(qName)) {
System.out.println("用户ID:" + currentId + ",姓名:" + currentName + ",年龄:" + currentAge + ",邮箱:" + currentEmail);
}
currentElement = "";
}
}
}两种解析方式的对比
DOM和SAX解析各有优劣,开发者可以根据实际需求选择:
| 对比项 | DOM解析 | SAX解析 |
|---|---|---|
| 内存占用 | 较高,需要加载整个文档到内存 | 较低,按需读取,不需要加载整个文档 |
| 解析速度 | 小文件速度快,大文件速度慢 | 大文件解析速度快 |
| 文档修改 | 支持修改文档内容 | 不支持修改文档内容 |
| 适用场景 | 小体积XML,需要修改内容的场景 | 大体积XML,只需要读取内容的场景 |
注意事项
- 解析XML时需要处理异常,比如文件不存在、XML格式错误等情况,实际开发中需要添加完善的异常处理逻辑。
- 如果XML文件包含DTD验证,可以通过
DocumentBuilderFactory或者SAXParserFactory设置是否开启验证。 - 解析大文件时优先选择SAX方式,避免内存溢出问题。