0%

StAX解析

StAX 解析:基于拉模式的 XML 解析方式

StAX(Streaming API for XML)是一种介于 DOM 和 SAX 之间的 XML 解析标准,它结合了 DOM 的灵活性和 SAX 的高效性,采用 “拉模式”(Pull Model)让应用程序主动控制解析过程,相比 SAX 的 “推模式”(Push Model)更易于使用。

StAX 解析的核心原理

StAX 解析的核心思想是 “应用程序主导解析流程”,其工作方式如下:

  1. 解析器初始化:创建 StAX 解析器(如XMLStreamReader),关联 XML 文档。
  2. 主动拉取事件:应用程序通过调用next()等方法主动获取下一个解析事件(如元素开始、文本内容、元素结束等)。
  3. 事件处理:根据拉取到的事件类型(如START_ELEMENTCHARACTERSEND_ELEMENT),应用程序自行决定如何处理(如提取数据、跳过节点)。
  4. 按需终止:解析过程完全由应用程序控制,可随时停止解析(如找到目标数据后)。

这种 “拉模式” 的优势在于:应用程序无需预先定义事件处理器,而是在需要时主动获取事件,代码逻辑更直观,尤其适合处理复杂 XML 结构。

StAX 的核心组件与事件类型

核心接口

StAX 提供了两种主要的解析接口,分别适用于不同场景:

  • XMLStreamReader:只读接口,用于从 XML 文档中拉取事件,是 StAX 的核心接口。
  • XMLEventReader:基于事件对象的只读接口,将解析事件封装为XMLEvent对象,提供更面向对象的操作方式。

其中,XMLStreamReader因轻量高效而更常用,以下主要围绕该接口展开。

常用方法(XMLStreamReader

方法 作用
int next() 推进到下一个事件,返回事件类型(如START_ELEMENT)。
String getLocalName() 获取当前元素的本地名称(不带命名空间前缀)。
String getText() 获取当前文本节点的内容。
int getAttributeCount() 获取当前元素的属性数量。
String getAttributeLocalName(int index) 获取指定索引的属性名称。
String getAttributeValue(int index) 获取指定索引的属性值。
String getAttributeValue(String namespaceURI, String localName) 根据命名空间和名称获取属性值。
boolean hasNext() 判断是否还有下一个事件。

常见事件类型(XMLStreamConstants

XMLStreamReadernext()方法返回的事件类型定义在XMLStreamConstants中,主要包括:

事件类型常量 含义
START_DOCUMENT 文档开始事件
END_DOCUMENT 文档结束事件
START_ELEMENT 元素开始事件(如<book>
END_ELEMENT 元素结束事件(如</book>
CHARACTERS 文本内容事件
ATTRIBUTE 属性事件(较少直接使用,通常在START_ELEMENT中处理属性)
COMMENT 注释事件
SPACE 空白字符事件

StAX 解析实战示例

以解析 MyBatis 的mapper.xml为例,演示XMLStreamReader的使用:

示例 XML 文档(UserMapper.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0"?>
<mapper namespace="com.example.UserMapper">
<select id="getUser" resultMap="userMap">
SELECT * FROM user WHERE id = #{id}
</select>
<insert id="insertUser">
INSERT INTO user (name) VALUES (#{name})
</insert>
</mapper>

使用XMLStreamReader解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;

public class StAXParserExample {
public static void main(String[] args) {
try {
// 1. 创建StAX解析器工厂
XMLInputFactory factory = XMLInputFactory.newInstance();
// 2. 获取XML输入流(从类路径加载资源)
InputStream stream = ClassLoader.getSystemResourceAsStream("UserMapper.xml");
// 3. 创建XMLStreamReader
XMLStreamReader reader = factory.createXMLStreamReader(stream);

// 4. 主动拉取事件并处理
while (reader.hasNext()) {
int eventType = reader.next(); // 推进到下一个事件

switch (eventType) {
case XMLStreamConstants.START_ELEMENT:
// 处理元素开始事件
String elementName = reader.getLocalName();
if ("mapper".equals(elementName)) {
// 获取namespace属性
String namespace = reader.getAttributeValue(null, "namespace");
System.out.println("namespace: " + namespace); // 输出:com.example.UserMapper
} else if ("select".equals(elementName) || "insert".equals(elementName)) {
// 获取id属性
String id = reader.getAttributeValue(null, "id");
System.out.println("找到" + elementName + "元素,id: " + id);
}
break;

case XMLStreamConstants.CHARACTERS:
// 处理文本内容(过滤空白字符)
String text = reader.getText().trim();
if (!text.isEmpty()) {
System.out.println("SQL内容: " + text);
}
break;

case XMLStreamConstants.END_DOCUMENT:
// 文档结束
System.out.println("解析完成。");
break;
}
}

// 关闭资源
reader.close();
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

输出结果

1
2
3
4
5
6
namespace: com.example.UserMapper
找到select元素,id: getUser
SQL内容: SELECT * FROM user WHERE id = #{id}
找到insert元素,id: insertUser
SQL内容: INSERT INTO user (name) VALUES (#{name})
解析完成。

StAX 与其他解析方式的对比

解析方式 核心模式 内存占用 灵活性 适用场景
DOM 树形结构 高(加载整个文档) 高(随机访问、修改) 中小型文档、需修改或频繁查询
SAX 推模式(事件驱动) 低(流式处理) 低(单向解析,需维护状态) 大型文档、仅读取数据
StAX 拉模式(应用主导) 低(流式处理) 中(主动控制,可跳转) 大型文档、需灵活处理事件

StAX 的优势

  1. 应用程序主导:无需预先定义事件处理器,解析流程更直观,易于调试。
  2. 低内存占用:流式处理,不加载整个文档,适合大型 XML。
  3. 灵活性高:可根据需求跳过无关节点,或在解析过程中动态调整逻辑。
  4. 支持写入:StAX 提供XMLStreamWriter接口,可方便地生成 XML 文档(DOM 和 SAX 的写入能力较弱)。

StAX 的局限性

  1. 不支持随机访问:虽比 SAX 灵活,但仍无法像 DOM 那样自由跳转节点。
  2. 状态管理:对于嵌套较深的 XML,仍需手动跟踪节点层级关系。

StAX 的典型应用场景

  1. 大型 XML 文档处理:如日志文件、数据备份文件等,StAX 的低内存特性可高效解析。
  2. 选择性解析:只需提取 XML 中的部分数据(如特定节点),可通过拉模式快速定位并跳过无关内容。
  3. XML 生成:通过XMLStreamWriter可简洁地生成 XML,比 DOM 更高效。
  4. 多文档并行处理:拉模式允许同时处理多个 XML 文档,适合批量数据处理。

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10