DOM (Document Object Model) 將 XML 載入內存形成樹狀結構,支持隨機訪問、修改、寫回文件,適合中小型配置文件或數據存儲場景。本文通過「學生管理系統」案例,完整演示 DOM 解析、節點操作、持久化全流程。
<?xml version="1.0" encoding="UTF-8"?>
<Students>
<student id="1">
<name>yyh1</name>
<age>22</age>
</student>
<student id="2">
<name>ttt</name>
<age>44</age>
</student>
...
</Students>
package com.briup.dom;
import org.w3c.dom.Document;
import javax.xml.parsers.*;
import java.io.File;
import java.io.IOException;
import org.xml.sax.SAXException;
public class DomUtils {
public static Document getDoc(File file) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(file); // 解析為 Document 樹
}
}
package com.briup.dom;
import org.w3c.dom.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.Scanner;
public class StudentManager {
private static final String FILE_PATH = "src/com/briup/dom/student.xml";
public static void main(String[] args) {
try {
Document doc = DomUtils.getDoc(new File(FILE_PATH));
Scanner input = new Scanner(System.in);
System.out.println("=== 學生管理系統 ===");
System.out.println("1. 添加學生");
System.out.println("2. 刪除學生");
System.out.println("3. 修改學生");
System.out.print("請選擇操作 (1-3): ");
int choice = input.nextInt();
input.nextLine(); // 消耗換行符
switch (choice) {
case 1: addStudent(doc, input); break;
case 2: delStudent(doc, input); break;
case 3: updStudent(doc, input); break;
default: System.out.println("無效選項");
}
} catch (Exception e) {
e.printStackTrace();
}
}
// --- 新增 ---
private static void addStudent(Document doc, Scanner input) throws TransformerException {
Element root = doc.getDocumentElement();
System.out.print("學號: ");
String id = input.nextLine();
// 唯一性校驗
NodeList list = doc.getElementsByTagName("student");
for (int i = 0; i < list.getLength(); i++) {
if (id.equals(list.item(i).getAttributes().getNamedItem("id").getNodeValue())) {
System.out.println("學號已存在!");
return;
}
}
System.out.print("姓名: ");
String name = input.nextLine();
System.out.print("年齡: ");
String age = input.nextLine();
// 創建節點樹
Element student = doc.createElement("student");
student.setAttribute("id", id);
student.appendChild(createElement(doc, "name", name));
student.appendChild(createElement(doc, "age", age));
root.appendChild(student);
persist(doc);
System.out.println("添加成功!");
}
// --- 刪除 ---
private static void delStudent(Document doc, Scanner input) throws TransformerException {
Element root = doc.getDocumentElement();
System.out.print("要刪除的學號: ");
String id = input.nextLine();
NodeList list = doc.getElementsByTagName("student");
for (int i = 0; i < list.getLength(); i++) {
Element student = (Element) list.item(i);
if (id.equals(student.getAttribute("id"))) {
root.removeChild(student);
persist(doc);
System.out.println("刪除成功!");
return;
}
}
System.out.println("未找到該學生。");
}
// --- 修改 ---
private static void updStudent(Document doc, Scanner input) throws TransformerException {
System.out.print("要修改的學號: ");
String id = input.nextLine();
NodeList list = doc.getElementsByTagName("student");
for (int i = 0; i < list.getLength(); i++) {
Element student = (Element) list.item(i);
if (id.equals(student.getAttribute("id"))) {
System.out.print("新姓名: ");
String name = input.nextLine();
System.out.print("新年齡: ");
String age = input.nextLine();
// 更新子節點文本
NodeList children = student.getChildNodes();
for (int j = 0; j < children.getLength(); j++) {
Node node = children.item(j);
if ("name".equals(node.getNodeName())) {
node.setTextContent(name);
} else if ("age".equals(node.getNodeName())) {
node.setTextContent(age);
}
}
persist(doc);
System.out.println("修改成功!");
return;
}
}
System.out.println("未找到該學生。");
}
// --- 輔助方法 ---
private static Element createElement(Document doc, String tag, String text) {
Element e = doc.createElement(tag);
e.setTextContent(text);
return e;
}
private static void persist(Document doc) throws TransformerException {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 格式化輸出
transformer.transform(new DOMSource(doc), new StreamResult(new File(FILE_PATH)));
}
}
| 操作 | 核心方法 | 說明 |
|---|---|---|
| 創建元素 | doc.createElement("tag") |
創建新節點 |
| 設置屬性 | element.setAttribute("id", "1") |
設置 XML 屬性 |
| 設置文本 | element.setTextContent("value") |
替換所有子文本節點 |
| 追加子節點 | parent.appendChild(child) |
構建樹結構 |
| 刪除節點 | parent.removeChild(child) |
從樹中移除 |
| 查找節點 | doc.getElementsByTagName("tag") |
返回 NodeList,支持遍歷 |
| 持久化 | Transformer.transform(DOMSource, StreamResult) |
將內存樹寫回文件 |
FILE_PATH 需相對項目根目錄或使用絕對路徑,IDEA 運行時工作目錄為項目根目錄。encoding="UTF-8"、讀寫均用 UTF-8,避免中文亂碼。transformer.setOutputProperty(OutputKeys.INDENT, "yes") 保持 XML 可讀性。掌握 DOM CRUD,輕鬆應對配置文件管理、小型數據存儲等場景。