首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java DOM 解析與生成 XML 完整實戰教學

     編輯:Java 相關知識

前言

DOM (Document Object Model) 將整個 XML 文檔載入記憶體形成樹狀結構,支援隨機訪問、修改、寫入,適合中小型 XML 處理。本文提供完整可運行代碼,涵蓋讀取、解析、修改、寫入全流程。

範例 XML (student.xml)

<?xml version="1.0" encoding="utf-8"?>
<學生花名冊>
    <學生 性別="男">
        <姓名>李華</姓名>
        <年齡>14</年齡>
    </學生>
    <學生 性別="男">
        <姓名>張三</姓名>
        <年齡>16</年齡>
    </學生>
</學生花名冊>

完整 Java 代碼

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; }
}

關鍵 API 對照表

任務核心類/方法
建立解析器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

常見坑與最佳實踐

  1. 命名空間:若 XML 含命名空間,需啟用 factory.setNamespaceAware(true) 並使用 getElementsByTagNameNS。
  2. 編碼一致:讀寫編碼保持一致(建議 UTF-8),避免中文亂碼。
  3. 大檔案改用 SAX/StAX:DOM 全量載入記憶體,>50MB 檔案易 OOM,改用流式解析。
  4. 異常處理:捕獲 ParserConfigurationException、SAXException、IOException、TransformerException。
  5. 實體類解耦:解析邏輯與 POJO 分離,便於單元測試與維護。

進階:使用 XPath 簡化查詢

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 等綁定框架。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved