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

Dom4j 實戰範例:XML 解析與生成的優雅實踐

     編輯:Java 相關知識

前言:為什麼選 Dom4j?

在 Java XML 處理陣營中,Dom4j 以「易用性」著稱:流暢的 API、XPath 原生支援、靈活的輸出格式、優異的效能。本文透過完整範例展示:從檔案讀取 → 解析提取 → 程式化建構 → 輸出檔案的完整閉環。

完整可執行範例程式碼


package xml;

import java.io.*;
import org.apache.log4j.Logger;
import org.dom4j.*;
import org.dom4j.io.SAXReader;

public class Dom4jDemo {
    private static final Logger logger = Logger.getLogger(Dom4jDemo.class);

    public static void main(String[] args) {
        // 1. 讀取 XML 檔案
        File inputFile = new File("ew.xml");
        SAXReader reader = new SAXReader();
        
        try {
            Document document = reader.read(inputFile);
            Element root = document.getRootElement();
            
            // 2. 提取根元素屬性
            String cmd = root.attributeValue("cmd");
            String version = root.attributeValue("version");
            logger.debug("Root element: " + root.getName());
            logger.debug("cmd=" + cmd + ", version=" + version);
            
            // 3. 導航提取子元素
            Element source = root.element("Source");
            String sourceType = source.attributeValue("type");
            String sourceUns = source.attributeValue("uns");
            logger.debug("Source type=" + sourceType + ", uns=" + sourceUns);
            
            Element username = root.element("Username");
            String userText = username.getTextTrim();
            logger.debug("Username=" + userText);
            
            // 4. 程式化建構新 XML
            Element user = DocumentHelper.createElement("User")
                .addAttribute("type", "user");
            user.addElement("name")
                .addAttribute("type", "PinYin")
                .setText("Julysea");
            user.addElement("age").setText("29");
            
            // 5. 輸出到檔案 (格式化)
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
            XMLWriter writer = new XMLWriter(
                new FileWriter("output.xml"), format);
            writer.write(user);
            writer.close();
            
            logger.info("XML 生成完成:output.xml");
            
        } catch (DocumentException | IOException e) {
            logger.error("XML 處理失敗", e);
        }
    }
}

關鍵技術點解析

1. 解析策略選擇

解析器適用場景記憶體特性
SAXReader (DOM 風格)中小型 XML、需隨機存取、多次遍歷完整樹載入記憶體
SAXReader + XPath大型 XML、只需提取特定節點可配合節點釋放優化
StAX (XMLStreamReader)超大型 XML、串流處理、單向遍歷事件驅動、常駐記憶體極低

2. XPath 強大查詢 (Dom4j 核心優勢)


// 絕對路徑
List nodes = document.selectNodes("/EW/Source/@type");

// 相對路徑 (從 root 起)
List users = root.selectNodes("//User[@type='admin']");

// 條件過濾
Element firstUser = (Element) root.selectSingleNode("User[name='Julysea']");

// 命名空間處理
Map nsMap = new HashMap();
nsMap.put("ns", "https://example.com/ns");
XPath xpath = document.createXPath("//ns:User", nsMap);

3. 輸出格式控制


// 緊湊格式 (生產環境傳輸)
OutputFormat compact = OutputFormat.createCompactFormat();

// 完美縮排 (開發除錯、配置檔)
OutputFormat pretty = OutputFormat.createPrettyPrint();
pretty.setIndent("  ");        // 兩空格縮排
pretty.setEncoding("UTF-8");   // 指定編碼
pretty.setNewlines(true);      // 換行
pretty.setTrimText(true);      // 修剪文字節點空白

4. 命名空間正確處理


// 建立帶命名空間的元素
Namespace ns = Namespace.get("ns", "https://example.com/ns");
Element root = DocumentHelper.createElement(QName.get("Root", ns));
root.add(Namespace.get("xsi", "https://www.w3.org/2001/XMLSchema-instance"));

// 輸出時自動處理前綴宣告

Log4j 配置檔 (log4j.properties)


log4j.rootLogger=DEBUG, Console, File

log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.appender.File=org.apache.log4j.RollingFileAppender
log4j.appender.File.File=./dom4j-demo.log
log4j.appender.File.MaxFileSize=500KB
log4j.appender.File.MaxBackupIndex=1
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

測試用 XML 範例 (ew.xml)


<?xml version="1.0" encoding="UTF-8"?>
<EW version="6.0" mod="Login" cmd="login">
  <SOURCE type="user" uns="">
    <USERNAME>zhangzhiyun@hp</USERNAME>
    <PASSWORD>111111</PASSWORD>
    <VERSION>6.01.06.00</VERSION>
  </SOURCE>
</EW>

常見坑點與最佳實踐

  • 編碼一致性:讀取、處理、輸出全鏈路指定 UTF-8,避免中文亂碼
  • 實體引用處理:輸出含特殊字元時,`setEscapeText(true)` 確保正確轉義
  • 大檔案記憶體壓力:超過 50MB XML 建議改用 StAX 或 SAX 事件驅動模式
  • XPath 注入防護:使用者輸入拼接 XPath 時,必須轉義或使用參數化
  • 命名空間陷阱:無命名空間查詢無法匹配有命名空間的元素,必須註冊 NamespaceContext

現代替代方案對比

庫優點缺點推薦場景
Dom4jAPI 優雅、XPath 強、效能好非標準、維護較緩既有專案維護、中等複雜度 XML
JDOM2純 Java、API 直觀效能略遜 Dom4j教學、中小專案
XOM極度嚴格符合 XML 標準學習曲線陡、API 較死板高可靠性要求系統
Jackson XMLPOJO 綁定、與 JSON 統一複雜 XML 結構映射困難資料傳輸物件序列化
StAX (JDK 內建)零依賴、串流、記憶體極低程式碼冗長、無隨機存取超大檔、高吞吐管道
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved