导读:本期聚焦于多肉创作的《Java DOM解析器怎么用 DOM解析XML的优缺点与方法》,敬请观看详情。为什么同样是解析XML文件,有人选择DOM,有人却坚持用SAX?答案取决于文件大小和业务场景。DOM解析器会把整个XML文档一次性加载进内存,构建成一棵树形结构,开发者可以随意遍历、修改、删除任意节点,操作方式直观且灵活,特别适合需要频繁读写XML内容的场景。但它的内存开销也随之而来,处理超大文件时容易出现内存溢出。本文详细讲解Java中DocumentBuilderFactory和DocumentBuilder的基本用法,包括如何获取Document对象、遍历节点、读取属性与文本内容,同时对比DOM与SAX、StAX的适用差异,帮助你根据实际情况选择合适的解析方案。

XML作为一种经典的数据交换格式,至今仍在配置文件、接口报文、Web服务等领域大量使用。Java提供了多种解析XML的方式,其中DOM(Document Object Model)是最容易上手、也最直观的一种。它把整个XML文档读入内存,形成一棵节点树,开发者可以像操作普通对象一样操作这棵树。本文将从DOM的工作原理讲起,给出完整的代码示例,并客观分析它的优缺点和适用场景。

Java DOM解析器怎么用 DOM解析XML的优缺点与方法

DOM解析XML的基本原理

DOM是W3C制定的一套标准接口,它将XML文档看作一个由节点组成的树形结构。树的根是Document对象,元素对应Element节点,文本内容对应Text节点,属性对应Attr节点。整个文档的层级关系和嵌套结构都被完整地映射到内存中,因此访问任意一个节点都不需要重新读取文件。

正因为文档被完整加载到内存,DOM支持随机访问:你可以先取第十个节点,再回头取第三个节点,甚至可以直接修改或删除某个节点后重新写回文件。这种灵活性是流式解析方式(如SAX)无法提供的。不过代价也很明显:一份100MB的XML文件,构建成DOM树后占用的内存可能是原始文件大小的3到5倍,这是由每个节点对象的额外开销造成的。

在Java中,DOM解析主要通过JAXP(Java API for XML Processing)提供的一组类完成,核心入口是DocumentBuilderFactoryDocumentBuilder。这些类都包含在JDK中,不需要额外引入第三方依赖,这也是DOM在Java世界里普及度很高的原因之一。

Java DOM解析的完整代码示例

下面通过一个具体的例子演示DOM解析的核心步骤。假设有一个students.xml文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<students>
    <student id="1001">
        <name>张三</name>
        <age>20</age>
    </student>
    <student id="1002">
        <name>李四</name>
        <age>22</age>
    </student>
</students>

解析这个文件的Java代码如下:

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
import java.io.File;

public class DomParseDemo {
    public static void main(String[] args) throws Exception {
        // 1. 创建解析器工厂,注意newInstance方法
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // 2. 通过工厂创建解析器对象
        DocumentBuilder builder = factory.newDocumentBuilder();
        // 3. 解析文件,得到代表整棵树的Document对象
        Document document = builder.parse(new File("students.xml"));

        // 4. 获取所有student元素,返回NodeList
        NodeList studentList = document.getElementsByTagName("student");
        for (int i = 0; i < studentList.getLength(); i++) {
            Element student = (Element) studentList.item(i);
            // 读取属性
            String id = student.getAttribute("id");
            // 读取子元素的文本内容
            String name = student.getElementsByTagName("name")
                                  .item(0).getTextContent();
            String age = student.getElementsByTagName("age")
                                 .item(0).getTextContent();
            System.out.println("学号:" + id + ",姓名:" + name + ",年龄:" + age);
        }
    }
}

代码中有几个关键点值得注意。getElementsByTagName返回的NodeList是按文档顺序排列的,配合索引可以逐个访问;getTextContent会返回元素内所有的文本内容,包括嵌套层级中的文本,比getFirstChild().getNodeValue()这种写法更简洁安全,因为它不依赖节点是否存在子节点。

还有一个新手常踩的坑:XML中的空白字符(比如标签之间的换行和缩进)会被当作Text节点保存到树中。如果直接用getFirstChild()去取name元素的文本,很可能拿到的是一个空白节点而不是文本本身。解决办法有三种:使用getTextContent()、手动遍历找到类型为Node.TEXT_NODE的节点,或者在工厂上调用factory.setIgnoringElementContentWhitespace(true)来忽略缩进空白。

除了读取,DOM还支持创建和修改节点。比如想在文档中新增一个student节点再写回文件,可以这样写:

// 创建新元素
Element newStudent = document.createElement("student");
newStudent.setAttribute("id", "1003");

Element name = document.createElement("name");
name.setTextContent("王五");
newStudent.appendChild(name);

Element age = document.createElement("age");
age.setTextContent("21");
newStudent.appendChild(age);

// 挂到根节点下
document.getDocumentElement().appendChild(newStudent);

// 写回文件
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(new DOMSource(document),
        new StreamResult(new File("students.xml")));

DOM解析的优缺点分析

先说优点。第一是编程模型直观,树形结构与XML的嵌套结构一一对应,代码可读性高,学习成本低。第二是支持随机访问和双向操作,既能读也能写,还能删除、移动节点,这对需要修改XML配置文件的场景非常友好。第三是API标准化,代码在Java、JavaScript、Python等语言中概念相通,迁移成本小。

缺点方面最突出的就是内存消耗。整个文档必须在内存中完整构建,文件越大,树越庞大。解析一个几百MB的XML文件时,堆内存很容易被耗尽,抛出OutOfMemoryError。其次是解析速度较慢,一次性加载的初始开销远大于流式解析。另外,如果只需要文档中的一小部分数据,把整棵树都加载进内存显然是一种浪费。

下表对三种常见解析方式做一个对比:

解析方式内存占用读写能力适用场景
DOM高,整树加载可读可写,随机访问小中型文件,需修改文档结构
SAX低,事件驱动只读,顺序访问超大文件,只需读取部分数据
StAX低,拉式解析可读可写,顺序访问大文件,需要控制解析节奏

如何选择合适的解析方式

选择解析方案时,可以从三个维度考虑:文件大小、是否需要修改文档、访问方式是否随机。如果文件在10MB以内,且业务上需要对XML进行增删改操作,DOM是首选,代码简单直接,维护成本低。如果文件达到几百MB甚至几个GB,或者只需要提取少数字段的值,就应该转向SAX或StAX这类流式解析。

实际项目中还有一种折中做法:先用SAX流式扫描过滤出需要的片段,再对片段单独构建DOM树进行精细操作。这样既避免了整棵大树撑爆内存,又保留了对目标数据的灵活处理能力。另外,如果XML结构固定且追求开发效率,也可以考虑JAXB这类对象绑定框架,它能把XML直接映射成Java对象,进一步简化代码。

最后提醒一点,解析外部来源的XML文件时要注意安全问题。建议在工厂上关闭外部实体引用,防止XXE攻击:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 禁用DTD,防止XXE注入攻击
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);

总的来说,DOM解析器是Java处理XML的基础工具,理解它的树形模型和内存特性,不仅能写出正确的解析代码,也能在架构选型时做出更合理的判断。小文件用DOM图省事,大文件换流式方案保安全,按场景做取舍才是工程上的正确姿势。

Java DOM解析XML解析DOM解析器修改时间:2026-09-09 03:18:39

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260909/53156.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。