- DOM (Document Object Model) 方式:将整个 XML 文档读入内存,形成一个树形结构,这种方式简单直观,适合小型 XML 文件,但如果 XML 文件很大,会消耗大量内存。
- SAX (Simple API for XML) / StAX (Streaming API for XML) 方式:事件驱动的解析方式,逐行读取 XML 文件,不会一次性加载整个文档到内存,这种方式性能好,内存占用低,适合处理大型 XML 文件。
下面我将详细介绍这两种方式,并提供完整的代码示例。

准备工作:确保你的字符串是有效的 XML
你需要确保你想要转换的字符串是一个格式良好的 XML,它必须有且仅有一个根元素,所有标签都必须正确闭合。
一个有效的 XML 字符串示例:
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book id="001">
<title>Java Programming</title>
<author>John Doe</author>
<price currency="USD">39.99</price>
</book>
<book id="002">
<title>Learning XML</title>
<author>Jane Smith</author>
<price currency="EUR">29.50</price>
</book>
</library>
使用 DOM (Document Object Model)
DOM 是最常见和最简单的方法,Java 标准库 javax.xml.parsers 提供了 DOM 解析器。
核心类
DocumentBuilderFactory: 创建DocumentBuilder的工厂类。DocumentBuilder: 负责将 XML 源(如文件、输入流、字符串)解析成Document对象。Document: 代表整个 XML 文档的内存树形结构。Node:Document、Element等所有节点的基类。Element: 代表 XML 中的一个元素(标签)。
完整代码示例
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
public class StringToXmlDom {
public static void main(String[] args) {
// 1. 定义你的 XML 字符串
String xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<library>"
+ " <book id=\"001\">"
+ " <title>Java Programming</title>"
+ " <author>John Doe</author>"
+ " <price currency=\"USD\">39.99</price>"
+ " </book>"
+ " <book id=\"002\">"
+ " <title>Learning XML</title>"
+ " <author>Jane Smith</author>"
+ " <price currency=\"EUR\">29.50</price>"
+ " </book>"
+ "</library>";
try {
// 2. 创建 DocumentBuilderFactory 和 DocumentBuilder
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
// 3. 将字符串转换为输入流并解析成 Document 对象
// 注意:StringReader 是 Reader 的实现,DocumentBuilder 也能处理
Document document = builder.parse(new InputSource(new StringReader(xmlString)));
// 4. (可选) 规范化文档,确保文本节点等被正确处理
document.getDocumentElement().normalize();
// 5. 开始遍历和操作 XML 树
System.out.println("根元素: " + document.getDocumentElement().getNodeName());
// 获取所有 'book' 节点
NodeList bookList = document.getElementsByTagName("book");
// 遍历 bookList
for (int i = 0; i < bookList.getLength(); i++) {
Node node = bookList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
System.out.println("\n当前 Book ID: " + element.getAttribute("id"));
// 获取 'title' 元素
NodeList titleList = element.getElementsByTagName("title");
Element titleElement = (Element) titleList.item(0);
System.out.println("标题: " + titleElement.getTextContent());
// 获取 'author' 元素
NodeList authorList = element.getElementsByTagName("author");
Element authorElement = (Element) authorList.item(0);
System.out.println("作者: " + authorElement.getTextContent());
// 获取 'price' 元素及其属性
NodeList priceList = element.getElementsByTagName("price");
Element priceElement = (Element) priceList.item(0);
System.out.println("价格: " + priceElement.getTextContent() + " " + priceElement.getAttribute("currency"));
}
}
} catch (Exception e) {
e.printStackTrace();
System.err.println("XML 解析错误: " + e.getMessage());
}
}
}
输出结果:

根元素: library
当前 Book ID: 001 Java Programming
作者: John Doe
价格: 39.99 USD
当前 Book ID: 002 Learning XML
作者: Jane Smith
价格: 29.50 EUR
使用 StAX (Streaming API for XML)
StAX 是一种更现代、更高效的流式 API,它允许你以“拉取”(pull)的方式读取 XML 事件,对于大型文件,StAX 的性能和内存效率远超 DOM。
核心类
XMLInputFactory: 创建XMLStreamReader的工厂类。XMLStreamReader: 逐个读取 XML 事件(如开始元素、结束元素、字符数据等)的读取器。
完整代码示例
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.StringReader;
public class StringToXmlStax {
public static void main(String[] args) {
String xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<library>"
+ " <book id=\"001\">"
+ " <title>Java Programming</title>"
+ " <author>John Doe</author>"
+ " <price currency=\"USD\">39.99</price>"
+ " </book>"
+ " <book id=\"002\">"
+ " <title>Learning XML</title>"
+ " <author>Jane Smith</author>"
+ " <price currency=\"EUR\">29.50</price>"
+ " </book>"
+ "</library>";
XMLInputFactory factory = XMLInputFactory.newInstance();
try {
// 创建 XMLStreamReader
XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xmlString));
String currentElement = null;
String currentId = null;
// 遍历所有 XML 事件
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
// 当遇到一个开始标签时
if ("book".equals(reader.getLocalName())) {
currentId = reader.getAttributeValue(null, "id");
System.out.println("\n当前 Book ID: " + currentId);
} else if ("title".equals(reader.getLocalName()) || "author".equals(reader.getLocalName()) || "price".equals(reader.getLocalName())) {
currentElement = reader.getLocalName();
}
break;
case XMLStreamConstants.CHARACTERS:
// 当遇到字符数据时
if (currentElement != null) {
String text = reader.getText().trim();
if (!text.isEmpty()) {
switch (currentElement) {
case "title":
System.out.println("标题: " + text);
break;
case "author":
System.out.println("作者: " + text);
break;
case "price":
String currency = reader.getAttributeValue(null, "currency");
System.out.println("价格: " + text + " " + currency);
break;
}
}
}
break;
case XMLStreamConstants.END_ELEMENT:
// 当遇到一个结束标签时
if ("book".equals(reader.getLocalName())) {
currentId = null;
}
currentElement = null; // 重置当前元素
break;
}
}
reader.close();
} catch (XMLStreamException e) {
e.printStackTrace();
System.err.println("StAX 解析错误: " + e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出结果:
当前 Book ID: 001 Java Programming
作者: John Doe
价格: 39.99 USD
当前 Book ID: 002 Learning XML
作者: Jane Smith
价格: 29.50 EUR
总结与对比
| 特性 | DOM (Document Object Model) | StAX (Streaming API for XML) |
|---|---|---|
| 处理方式 | 将整个 XML 文档加载到内存中,形成树状结构。 | 事件驱动,逐行读取,不一次性加载整个文档。 |
| 内存消耗 | 高,与 XML 文件大小成正比。 | 低,内存占用恒定,适合大文件。 |
| 性能 | 较慢,尤其是在构建整个树时。 | 较快,特别是对于只读操作。 |
| 易用性 | 非常简单直观,易于理解和使用,适合小型文件和快速开发。 | 相对复杂,需要手动处理事件和状态管理。 |
| 适用场景 | - XML 文件较小。 - 需要频繁地在文档中任意位置进行读写操作。 - 开发时间短,希望代码简单。 |
- XML 文件非常大。 - 只需要遍历一次 XML 文件。 - 对内存和性能有严格要求。 |
如何选择?
- 对于初学者或小型项目:直接使用 DOM,它最简单,代码量少,不容易出错。
- 对于处理大型 XML 文件或企业级应用:强烈推荐使用 StAX 或 SAX,它能有效避免
OutOfMemoryError,并提供更好的性能。
还有像 JDOM 和 DOM4J 这样的第三方库,它们提供了比标准 DOM 更友好、更强大的 API,是许多 Java 项目的首选,但如果不想引入额外依赖,标准的 javax.xml 包已经足够强大。
