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

Java DOM 解析 XML 完整範例:樹狀模型隨機存取、元素屬性與文字內容提取

     編輯:Java 相關知識

DOM (Document Object Model) 將整份 XML 載入記憶體構建樹狀結構,支援隨機存取、XPath 查詢、修改寫入。適合中小型 XML、需多次遍歷/修改的場景。本文提供完整解析範例,示範元素屬性、巢狀子元素、文字內容的提取與物件映射。

範例 XML (People.xml)

<?xml version="1.0" encoding="UTF-8"?>
<PeopleList>
    <People id="1" en="John">
        <Name>張三</Name>
        <Age>25</Age>
    </People>
    <People id="2" en="Jane">
        <Name>李四</Name>
        <Age>30</Age>
    </People>
</PeopleList>

資料模型

public class People {
    private String id, name, englishName, age;
    // Getter/Setter/建構子/toString 略
}

完整解析程式碼

import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class DomXML {
    public static void main(String[] args) {
        File file = new File("e:/People.xml");
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // factory.setNamespaceAware(true); // 若 XML 有命名空間
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(file);
            doc.getDocumentElement().normalize(); // 合併相鄰文字節點

            List peopleList = new ArrayList<>();
            NodeList peopleNodes = doc.getElementsByTagName("People");

            for (int i = 0; i < peopleNodes.getLength(); i++) {
                Node node = peopleNodes.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element peopleElem = (Element) node;
                    People people = new People();

                    // 1. 讀取屬性
                    people.setId(peopleElem.getAttribute("id"));
                    people.setEnglishName(peopleElem.getAttribute("en"));

                    // 2. 讀取子元素文字內容
                    NodeList children = peopleElem.getChildNodes();
                    for (int j = 0; j < children.getLength(); j++) {
                        Node child = children.item(j);
                        if (child.getNodeType() == Node.ELEMENT_NODE) {
                            Element childElem = (Element) child;
                            String tagName = childElem.getTagName();
                            String textContent = childElem.getTextContent().trim();

                            switch (tagName) {
                                case "Name": people.setName(textContent); break;
                                case "Age": people.setAge(textContent); break;
                            }
                        }
                    }
                    peopleList.add(people);
                }
            }

            // 輸出驗證
            for (People p : peopleList) {
                System.out.println(p.getId() + "\t" + p.getName() + "\t" + p.getEnglishName() + "\t" + p.getAge());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

關鍵 API 與節點類型對照

介面/方法用途備註
DocumentBuilderFactory建立解析器工廠可設定驗證、命名空間、忽略註解等
DocumentBuilder.parse()解析輸入源 → Document支援 File, InputStream, InputSource, URI
doc.getDocumentElement()取得根元素對應 XML 根標籤
getElementsByTagName()遞迴搜尋所有同名元素回傳 NodeList (即時檢視)
Element.getAttribute()讀取屬性值屬性不存在回傳空字串
Node.getTextContent()取得元素及所有後代文字包含換行縮排,需 trim()
Node.getNodeType()判斷節點類型ELEMENT_NODE=1, TEXT_NODE=3, 等
doc.normalize()合併相鄰文字節點解決格式化 XML 產生多文字節點問題

DOM vs SAX vs StAX 選型指南

特性DOMSAXStAX
記憶體模型完整樹狀結構 (高)串流事件 (極低)游標/迭代器 (低)
存取模式隨機、雙向單向、唯讀單向、可拉取
修改/寫入原生支援不支援支援 (XMLStreamWriter)
XPath 支援原生需自行實作需額外庫
適用場景小檔、多遍歷、需修改大檔、單遍歷、提取部分大檔、需控制流程、雙向

常見陷阱與最佳實踐

  • 空白文字節點:格式化 XML 的縮排換行會產生 TEXT_NODE,必須檢查 getNodeType() == ELEMENT_NODE
  • 命名空間:若 XML 有 xmlns,需啟用 factory.setNamespaceAware(true) 並使用 getElementsByTagNameNS()
  • 大檔案 OOM:DOM 載入整份文件,100MB+ XML 易爆記憶體 → 改用 SAX/StAX
  • 編碼問題:XML 宣告 encoding 與實際檔案編碼必須一致,解析器自動處理
  • 防止 XXE 攻擊:解析非信任 XML 時必須關閉外部實體:
    factory.setFeature("https://apache.org/xml/features/disallow-doctype-decl", true);
    factory.setFeature("https://xml.org/sax/features/external-general-entities", false);
    factory.setFeature("https://xml.org/sax/features/external-parameter-entities", false);
    factory.setXIncludeAware(false);
    factory.setExpandEntityReferences(false);

進階:XPath 查詢簡化提取

import javax.xml.xpath.*;

XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
NodeList nodes = (NodeList) xpath.evaluate("//People", doc, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
    Element e = (Element) nodes.item(i);
    String id = e.getAttribute("id");
    String name = xpath.evaluate("Name/text()", e);
    String age = xpath.evaluate("Age/text()", e);
    // ...
}

DOM 解析以直觀樹狀模型和豐富 API 成為中小型 XML 處理的首選,配合 XPath 更能大幅簡化提取邏輯。

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