杰瑞科技汇

Java DOM如何读写XML?

DOM(Document Object Model,文档对象模型)是 W3C 组织推荐的处理 XML 的一种方式,它将整个 XML 文档加载到内存中,解析成一个树形结构,你可以像操作树一样,轻松地访问、添加、修改或删除文档中的任何节点。

Java DOM如何读写XML?-图1
(图片来源网络,侵删)

核心特点:

  • 树形结构:整个 XML 文档被转换成一个由节点(Node)组成的树。
  • 内存消耗大:因为要把整个文档都加载到内存,所以对于非常大的 XML 文件,DOM 解析可能会消耗大量内存,甚至导致内存溢出。
  • 随机访问:由于整个文档都在内存中,你可以随时访问任何一个节点,操作非常灵活。

准备工作:引入依赖

标准的 Java 开发环境(JDK)已经包含了处理 XML 所需的 org.w3c.domjavax.xml.parsers 等包,所以你不需要额外引入任何依赖


XML 示例文件

为了演示,我们先创建一个名为 students.xml 的文件。

students.xml

Java DOM如何读写XML?-图2
(图片来源网络,侵删)
<?xml version="1.0" encoding="UTF-8"?>
<students>
    <student id="S001">
        <name>张三</name>
        <age>20</age>
        <gender>男</gender>
    </student>
    <student id="S002">
        <name>李四</name>
        <age>21</age>
        <gender>女</gender>
    </student>
</students>

解析 XML (读)

解析 XML 的主要步骤是:

  1. 创建一个 DocumentBuilderFactory 实例。
  2. 通过工厂创建一个 DocumentBuilder 实例。
  3. 使用 DocumentBuilderparse() 方法解析 XML 文件,得到一个 Document 对象(即整个 XML 的内存树)。
  4. 通过 Document 对象获取根节点,然后通过节点方法(如 getElementsByTagName(), getChildNodes() 等)遍历和查找节点。

示例代码:读取 students.xml

import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.File;
public class ReadXmlWithDom {
    public static void main(String[] args) {
        try {
            // 1. 创建 DocumentBuilderFactory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 2. 创建 DocumentBuilder
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 3. 解析 XML 文件,得到 Document 对象
            // File xmlFile = new File("students.xml");
            // Document document = builder.parse(xmlFile);
            // 也可以从 URL 或输入流解析
            Document document = builder.parse(new File("students.xml"));
            // 4. 获取文档的根节点
            Element root = document.getDocumentElement();
            System.out.println("根节点名称: " + root.getNodeName());
            // 5. 获取所有名为 "student" 的节点列表
            NodeList studentList = root.getElementsByTagName("student");
            System.out.println("\n--- 遍历所有学生信息 ---");
            // 6. 遍历 studentList
            for (int i = 0; i < studentList.getLength(); i++) {
                Node studentNode = studentList.item(i);
                // 确保节点是 Element 类型
                if (studentNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element studentElement = (Element) studentNode;
                    // 获取 id 属性
                    String id = studentElement.getAttribute("id");
                    System.out.println("学生ID: " + id);
                    // 获取 name, age, gender 子节点的文本内容
                    String name = studentElement.getElementsByTagName("name").item(0).getTextContent();
                    String age = studentElement.getElementsByTagName("age").item(0).getTextContent();
                    String gender = studentElement.getElementsByTagName("gender").item(0).getTextContent();
                    System.out.println("  姓名: " + name);
                    System.out.println("  年龄: " + age);
                    System.out.println("  性别: " + gender);
                    System.out.println("--------------------");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

代码解释:

  • DocumentBuilderFactoryDocumentBuilder 是创建解析器的标准工厂模式。
  • builder.parse(file) 将 XML 文件解析成 Document 对象。
  • document.getDocumentElement() 获取 XML 的根元素(在这里是 <students>)。
  • root.getElementsByTagName("student") 获取所有名为 student 的元素节点,返回一个 NodeList
  • node.getNodeType() == Node.ELEMENT_NODE 用于判断节点是否是元素节点(<tag>),而不是文本节点(如换行符和空格)或注释节点。
  • element.getAttribute("id") 获取元素的属性值。
  • element.getElementsByTagName("name").item(0) 获取第一个匹配的子元素节点。
  • .getTextContent() 获取该节点及其所有子节点的文本内容合并后的字符串。

生成 XML (写)

生成 XML 的主要步骤是:

Java DOM如何读写XML?-图3
(图片来源网络,侵删)
  1. 同样,创建 DocumentBuilderFactoryDocumentBuilder
  2. 使用 DocumentBuildernewDocument() 方法创建一个空的 Document 对象。
  3. 使用 Document 接口提供的 createElement(), createTextNode(), setAttribute() 等方法在内存中构建 XML 树。
  4. 使用 TransformerFactoryTransformer 将内存中的 Document 对象写入到文件或输出流中。

示例代码:创建一个新的 new_students.xml 文件

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
public class WriteXmlWithDom {
    public static void main(String[] args) {
        try {
            // 1. 创建 DocumentBuilderFactory 和 DocumentBuilder
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 2. 创建一个新的 Document 对象
            Document document = builder.newDocument();
            // 3. 创建根元素 <classroom>
            Element rootElement = document.createElement("classroom");
            document.appendChild(rootElement);
            // 4. 创建第一个学生 <student>
            Element student1 = document.createElement("student");
            student1.setAttribute("id", "C001");
            Element name1 = document.createElement("name");
            name1.appendChild(document.createTextNode("王五"));
            Element age1 = document.createElement("age");
            age1.appendChild(document.createTextNode("22"));
            student1.appendChild(name1);
            student1.appendChild(age1);
            rootElement.appendChild(student1);
            // 5. 创建第二个学生 <student>
            Element student2 = document.createElement("student");
            student2.setAttribute("id", "C002");
            Element name2 = document.createElement("name");
            name2.appendChild(document.createTextNode("赵六"));
            Element age2 = document.createElement("age");
            age2.appendChild(document.createTextNode("23"));
            student2.appendChild(name2);
            student2.appendChild(age2);
            rootElement.appendChild(student2);
            // 6. 将 Document 对象写入 XML 文件
            // 创建 TransformerFactory
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            // 创建 Transformer
            Transformer transformer = transformerFactory.newTransformer();
            // 设置输出格式 (可选,但推荐)
            transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 格式化输出
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); // 缩进量
            // 创建 DOMSource (源)
            DOMSource source = new DOMSource(document);
            // 创建 StreamResult (目标)
            StreamResult result = new StreamResult(new File("new_students.xml"));
            // 执行转换
            transformer.transform(source, result);
            System.out.println("XML 文件生成成功: new_students.xml");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

代码解释:

  • builder.newDocument() 创建一个空的文档。
  • document.createElement("tag") 创建一个新的元素节点。
  • document.createTextNode("text") 创建一个文本节点。
  • element.appendChild(node) 将一个子节点添加到父节点。
  • element.setAttribute("key", "value") 为元素添加属性。
  • TransformerTransformerFactory 是将内存中的 DOM 树序列化为 XML 文档的核心。
    • DOMSource:表示转换的源,即我们创建的 Document 对象。
    • StreamResult:表示转换的目标,可以是一个 FileOutputStreamWriter
    • transformer.transform(source, result):执行转换操作。

执行后,会生成一个 new_students.xml 文件,内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<classroom>
    <student id="C001">
        <name>王五</name>
        <age>22</age>
    </student>
    <student id="C002">
        <name>赵六</name>
        <age>23</age>
    </student>
</classroom>

修改现有 XML

修改 XML 结合了“读”和“写”的步骤,先读取现有 XML 到内存,然后修改 DOM 树,最后再写回文件。

示例代码:在 students.xml 中添加一个新学生

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
public class ModifyXmlWithDom {
    public static void main(String[] args) {
        try {
            // 1. 解析现有文件
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new File("students.xml"));
            // 2. 获取根节点
            Element root = document.getDocumentElement();
            // 3. 创建新学生节点
            Element newStudent = document.createElement("student");
            newStudent.setAttribute("id", "S003");
            Element name = document.createElement("name");
            name.appendChild(document.createTextNode("孙七"));
            newStudent.appendChild(name);
            Element age = document.createElement("age");
            age.appendChild(document.createTextNode("19"));
            newStudent.appendChild(age);
            Element gender = document.createElement("gender");
            gender.appendChild(document.createTextNode("男"));
            newStudent.appendChild(gender);
            // 4. 将新学生添加到根节点
            root.appendChild(newStudent);
            // 5. 将修改后的 Document 写回文件
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            DOMSource source = new DOMSource(document);
            StreamResult result = new StreamResult(new File("students.xml")); // 覆盖原文件
            transformer.transform(source, result);
            System.out.println("XML 文件修改成功,新学生已添加。");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

DOM vs. SAX (简单对比)

在选择解析器时,了解 DOM 和 SAX 的区别很重要。

特性 DOM (Document Object Model) SAX (Simple API for XML)
工作方式 将整个 XML 文档加载到内存,构建树形结构。 事件驱动,解析器从头到尾读取 XML,当遇到元素开始、结束、文本等时,触发相应的事件。
内存占用 ,与文件大小成正比,大文件可能导致内存溢出。 ,解析时只保留当前节点信息,内存占用恒定。
访问方式 随机访问,可以随时访问任意节点。 顺序访问,只能从前往后遍历,无法回头。
操作方式 易于修改,可以直接在内存树中增删改节点。 只读,不适合修改 XML,适合提取数据。
速度 对于小文件,解析速度较快,对于大文件,因加载慢而整体较慢。 解析速度通常很快,尤其适合大文件。
适用场景 XML 文件不大,需要频繁访问和修改数据。 XML 文件很大,只需要读取一次并提取特定信息。
  • 如果你的 XML 文件不大,并且需要对它进行复杂的查询和修改,DOM 是最佳选择,因为它简单直观。
  • 如果你的 XML 文件非常大(几百MB或GB级别),或者你只需要读取其中的部分数据,SAX 或 Pull 解析器会更高效。
分享:
扫描分享到社交APP
上一篇
下一篇