DOM (Document Object Model) 將整個 XML 文檔載入記憶體形成樹狀結構,支援隨機訪問、修改、寫入,適合中小型 XML 處理。本文提供完整可運行代碼,涵蓋讀取、解析、修改、寫入全流程。
<?xml version="1.0" encoding="utf-8"?>
<學生花名冊>
<學生 性別="男">
<姓名>李華</姓名>
<年齡>14</年齡>
</學生>
<學生 性別="男">
<姓名>張三</姓名>
<年齡>16</年齡>
</學生>
</學生花名冊>
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
public class XMLDemo {
private List students = new ArrayList<>();
/** 讀取並解析 XML */
public List readXMLFile(String filePath) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File(filePath));
Element root = doc.getDocumentElement(); // 學生花名冊
NodeList studentNodes = root.getElementsByTagName("學生");
for (int i = 0; i < studentNodes.getLength(); i++) {
Element stuElem = (Element) studentNodes.item(i);
Student stu = new Student();
stu.setSex(stuElem.getAttribute("性別"));
// 取姓名
Element nameElem = (Element) stuElem.getElementsByTagName("姓名").item(0);
stu.setName(nameElem.getTextContent());
// 取年齡
Element ageElem = (Element) stuElem.getElementsByTagName("年齡").item(0);
stu.setAge(Integer.parseInt(ageElem.getTextContent()));
students.add(stu);
}
return students;
}
/** 將物件列表寫入 XML */
public void writeXMLFile(String outPath) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
// 建立根元素
Element root = doc.createElement("學生花名冊");
doc.appendChild(root);
for (Student s : students) {
Element stuElem = doc.createElement("學生");
stuElem.setAttribute("性別", s.getSex());
root.appendChild(stuElem);
Element nameElem = doc.createElement("姓名");
nameElem.appendChild(doc.createTextNode(s.getName()));
stuElem.appendChild(nameElem);
Element ageElem = doc.createElement("年齡");
ageElem.appendChild(doc.createTextNode(String.valueOf(s.getAge())));
stuElem.appendChild(ageElem);
}
// 序列化輸出
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{https://xml.apache.org/xslt}indent-amount", "4");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new FileOutputStream(outPath));
transformer.transform(source, result);
System.out.println("XML 寫入完成:" + outPath);
}
public static void main(String[] args) {
XMLDemo demo = new XMLDemo();
try {
// 讀取
List list = demo.readXMLFile("E:/student.xml");
for (Student s : list) {
System.out.println(s.getName() + "\t" + s.getAge() + "\t" + s.getSex());
}
// 寫入副本
demo.writeXMLFile("src/stucopy.xml");
} catch (Exception e) {
e.printStackTrace();
}
}
}
/** 學生實體類 */
class Student {
private String sex, name;
private int age;
// Getter/Setter 省略
public String getSex() { return sex; }
public void setSex(String sex) { this.sex = sex; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
| 任務 | 核心類/方法 |
|---|---|
| 建立解析器 | DocumentBuilderFactory.newInstance() → newDocumentBuilder() |
| 解析檔案 | builder.parse(File/InputStream) |
| 取根元素 | doc.getDocumentElement() |
| 按標籤查找 | element.getElementsByTagName("tag") |
| 取屬性值 | element.getAttribute("attr") |
| 取文字內容 | node.getTextContent() (JDK 1.5+) 或 node.getFirstChild().getNodeValue() |
| 創建元素 | doc.createElement("tag") |
| 創建文字節點 | doc.createTextNode("content") |
| 序列化輸出 | TransformerFactory → Transformer → transform(DOMSource, StreamResult) |
| 格式化縮進 | setOutputProperty(OutputKeys.INDENT, "yes") + indent-amount |
factory.setNamespaceAware(true) 並使用 getElementsByTagNameNS。ParserConfigurationException、SAXException、IOException、TransformerException。XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
NodeList nodes = (NodeList) xpath.evaluate("//學生[性別='女']", doc, XPathConstants.NODESET);
XPath 適合複雜條件查詢,代碼更簡潔。
DOM API 雖然較為冗長,但提供完整的樹操作能力。掌握 DocumentBuilder、Element/Node 遍歷、Transformer 序列化三大核心流程,即可應對絕大多數 XML 讀寫需求。大檔案或高效能場景請轉向 SAX/StAX 或 Jackson XML、JAXB 等綁定框架。