JAXP全称是Java API for XML Processing,是Java平台提供的用于处理XML的标准API,它定义了统一的接口来调用不同的XML解析器,不需要开发者直接依赖具体的解析器实现,降低了代码的耦合度。

JAXP支持的两种解析方式
JAXP主要封装了DOM和SAX两种解析模式的调用,两种模式各有适用场景,我们可以根据实际需求选择:
- DOM解析:将整个XML文档加载到内存中,构建成树形节点结构,开发者可以随机访问、修改任意节点,适合需要频繁操作文档内容的场景,缺点是文档过大时内存占用高。
- SAX解析:基于事件驱动,逐行扫描XML文档,遇到标签、文本等内容时触发对应事件,开发者通过实现事件处理器来处理内容,内存占用低,适合处理大文件,但只能顺序读取,不支持修改文档。
DOM方式解析XML示例
首先准备一个简单的XML测试文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user id="1">
<name>张三</name>
<age>25</age>
</user>
<user id="2">
<name>李四</name>
<age>28</age>
</user>
</users>下面是使用JAXP的DOM方式解析上述XML的代码:
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;
public class JAXPDOMDemo {
public static void main(String[] args) throws Exception {
// 创建DOM解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 获取DOM解析器
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析XML文件,得到Document对象(整个文档的树形结构根节点)
Document document = builder.parse("users.xml");
// 获取所有user节点
NodeList userNodes = document.getElementsByTagName("user");
// 遍历所有user节点
for (int i = 0; i < userNodes.getLength(); i++) {
Element userElement = (Element) userNodes.item(i);
// 获取user节点的id属性
String id = userElement.getAttribute("id");
// 获取name子节点的文本内容
String name = userElement.getElementsByTagName("name").item(0).getTextContent();
// 获取age子节点的文本内容
String age = userElement.getElementsByTagName("age").item(0).getTextContent();
System.out.println("用户ID:" + id + ",姓名:" + name + ",年龄:" + age);
}
}
}SAX方式解析XML示例
SAX解析需要实现事件处理器,下面是使用JAXP的SAX方式解析同样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;
public class JAXPSAXDemo {
public static void main(String[] args) throws Exception {
// 创建SAX解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
// 获取SAX解析器
SAXParser parser = factory.newSAXParser();
// 解析XML文件,传入自定义的事件处理器
parser.parse("users.xml", new MySAXHandler());
}
}
// 自定义SAX事件处理器,继承DefaultHandler
class MySAXHandler extends DefaultHandler {
private String currentTag = null;
// 遇到开始标签时触发
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
currentTag = qName;
// 如果是user标签,打印id属性
if ("user".equals(qName)) {
System.out.print("用户ID:" + attributes.getValue("id") + ",");
}
}
// 遇到文本内容时触发
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// 只处理name和age标签的文本内容
if ("name".equals(currentTag) || "age".equals(currentTag)) {
String content = new String(ch, start, length);
System.out.print(("name".equals(currentTag) ? "姓名:" : "年龄:") + content + ",");
}
}
// 遇到结束标签时触发
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("user".equals(qName)) {
System.out.println(); // 每个user节点解析完换行
}
currentTag = null;
}
}两种方式的选型建议
如果XML文件较小,且需要修改文档内容、随机访问节点,优先选择DOM解析;如果XML文件体积大,只需要读取内容不需要修改,优先选择SAX解析。JAXP的优势在于统一了调用接口,后续如果需要更换底层解析器,只需要修改工厂配置即可,不需要重写大量解析逻辑。