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

Java DOM 解析 XML 完整實戰:從文件加載到節點遍歷

     編輯:Java 相關知識

DOM 解析器特點

  • 樹模型:一次性將整個 XML 載入記憶體構建 DOM 樹
  • 雙向導航:可任意訪問父/子/兄弟節點
  • 適合場景:小型文檔(< 50MB)、需隨機訪問、頻繁修改
  • 缺點:記憶體佔用大,大文件易 OOM

核心 API 速查

類/接口作用
DocumentBuilderFactory工廠模式獲取解析器實例
DocumentBuilder將 XML 文件/流解析為 Document 對象
DocumentDOM 樹根節點,代表整個文檔
Element元素節點,可獲取屬性、子節點
Node/NodeList通用節點接口與節點列表

完整代碼實戰

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

public class XmlDomParserDemo {
    public static void main(String[] args) throws Exception {
        // 1. 獲取工廠與構建器
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // 可選:啟用命名空間感知、驗證、忽略註釋等
        // factory.setNamespaceAware(true);
        DocumentBuilder builder = factory.newDocumentBuilder();

        // 2. 解析文件生成 Document
        File xmlFile = new File("test.xml");
        Document doc = builder.parse(xmlFile);

        // 3. 獲取根元素
        Element root = doc.getDocumentElement();
        System.out.println("根元素: " + root.getNodeName()); // Accounts

        // 4. 遍歷子節點
        NodeList accounts = root.getChildNodes();
        for (int i = 0; i < accounts.getLength(); i++) {
            Node node = accounts.item(i);
            // 過濾文本節點(換行、縮進產生的 #text)
            if (node.getNodeType() != Node.ELEMENT_NODE) continue;

            Element account = (Element) node;
            String type = account.getAttribute("type");
            System.out.println("\n找到賬號,類型: " + type);

            // 5. 解析子元素
            NodeList fields = account.getChildNodes();
            for (int j = 0; j < fields.getLength(); j++) {
                Node field = fields.item(j);
                if (field.getNodeType() != Node.ELEMENT_NODE) continue;

                String tagName = field.getNodeName();
                String text = field.getTextContent().trim();
                switch (tagName) {
                    case "code":  System.out.println("卡號: " + text); break;
                    case "pass":  System.out.println("密碼: " + text); break;
                    case "name":  System.out.println("姓名: " + text); break;
                    case "money": System.out.println("餘額: " + text); break;
                }
            }
        }
    }
}

測試用 test.xml

<?xml version="1.0" encoding="GBK"?>
<Accounts>
  <Account type="type1">
    <code>100001</code>
    <pass>123</pass>
    <name>李四</name>
    <money>1000000.00</money>
  </Account>
  <Account type="type2">
    <code>100002</code>
    <pass>123</pass>
    <name>張三</name>
    <money>1000.00</money>
  </Account>
</Accounts>

輸出結果

根元素: Accounts

找到賬號,類型: type1
卡號: 100001
密碼: 123
姓名: 李四
餘額: 1000000.00

找到賬號,類型: type2
卡號: 100002
密碼: 123
姓名: 張三
餘額: 1000.00

進階技巧與避坑

  1. 命名空間處理:若 XML 含 xmlns,需 factory.setNamespaceAware(true) 並使用 getElementsByTagNameNS()
  2. 實體解析:防止 XXE 攻擊,生產環境應禁用外部實體:factory.setFeature("https://apache.org/xml/features/disallow-doctype-decl", true)
  3. 編碼一致性:XML 聲明 encoding 需與文件實際編碼一致,否則中文亂碼
  4. 大文件替代方案:>50MB 改用 SAX (事件驅動) 或 StAX (拉取流) 流式解析,記憶體常數級
  5. XPath 簡化查詢:XPathFactory.newInstance().newXPath().compile("//Account[@type='type1']/code/text()").evaluate(doc)

總結

DOM 解析以 直觀的樹操作 見長,適合中小型 XML 配置文件、報文解析。掌握 DocumentBuilderFactory → DocumentBuilder → Document → Element/NodeList 核心鏈路,配合節點類型過濾 (Node.ELEMENT_NODE) 與 getTextContent(),即可高效完成 90% 的 XML 讀取需求。大文件、高併發場景請果斷切換至 StAX/SAX。

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