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

基於 JDOM 的 XML 讀寫工具類實戰:三層結構精確增量更新

     編輯:Java 相關知識

業務場景與數據模型

需求:管理三層結構 XML (Application → Group@name → key[]),支援按 Group 名稱查詢所有 key、檢查 key 是否存在、新增 Group/key 且去重。XML 範例:



  
    loops
    look
  

XMLReader 核心功能解析

1. 建構器:SAXBuilder 載入文檔


public XMLReader(String xmlFile) {
    try {
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(new FileInputStream(xmlFile));
        this.rootElement = doc.getRootElement();
    } catch (IOException | JDOMException e) {
        this.rootElement = null; // 標記載入失敗
    }
}

2. 精確查詢:三層導航方法

  • getElement(root, groupName):返回指定 Group 下所有 key 文本列表
  • checkElement(root, groupName):檢查 Group 是否存在,返回 Element 供後續操作
  • checkElementc(root, groupName, keyName):檢查具體 key 是否存在

實現邏輯:迭代子元素 → 比對 name 屬性 → 深入下一層 → 收集/比對文本值。注意原代碼 result.add() 前未初始化 List,會拋 NPE,需修正為 List result = new ArrayList<>();。

XMLWriter 增量寫入邏輯深度解析

核心方法 writerElement(xmlFile, groupName, keyName) 實現「不存在才新增」的冪等性:


public void writerElement(String xmlFile, String groupName, String keyName) {
    Document doc;
    Element root, groupElem, keyElem;
    
    XMLReader reader = new XMLReader(xmlFile);
    if (reader.getRootElement() == null) { // 文檔不存在或為空
        root = new Element("Application");
        doc = new Document(root);
        groupElem = createGroup(groupName, keyName);
        root.addContent(groupElem);
    } else { // 文檔存在
        root = reader.getRootElement();
        doc = root.getDocument();
        
        Element existingGroup = reader.checkElement(root, groupName);
        if (existingGroup != null) { // Group 存在
            if (reader.checkElementc(root, groupName, keyName) == null) { // key 不存在
                keyElem = new Element("key").setText(keyName);
                existingGroup.addContent(keyElem);
            }
            // key 已存在 → 什麼都不做 (冪等)
        } else { // Group 不存在
            groupElem = createGroup(groupName, keyName);
            root.addContent(groupElem);
        }
    }
    
    // 統一寫入,保持格式
    XMLOutputter fmt = new XMLOutputter(Format.getPrettyFormat().setEncoding("GB2312"));
    try (FileWriter fw = new FileWriter(xmlFile)) {
        fmt.output(doc, fw);
    } catch (IOException e) { throw new RuntimeException(e); }
}

private Element createGroup(String name, String key) {
    Element group = new Element("Group");
    group.setAttribute("name", name);
    group.addContent(new Element("key").setText(key));
    return group;
}

關鍵設計亮點與改進建議

亮點說明
分層檢查避免重複先查 Group 再查 key,邏輯清晰符合業務語義
複用 XMLReader讀寫分離,Writer 內部調用 Reader 復用查詢邏輯
Document 追蹤機制JDOM 的 element.getDocument() 自動維護樹關係,寫入時無需手動拼裝
格式化輸出Format.getPrettyFormat() 自動縮排換行,生成可讀 XML

代碼缺陷與重構要點

  1. NPE 風險:getElement() 中 result 未初始化
  2. 編碼硬編碼:構建器與輸出器均寫死 GB2312,應提取為參數或 UTF-8
  3. 異常處理吞噬:建構器捕獲異常僅置 null,調用者無法區分「文件不存在」與「格式錯誤」
  4. 線程不安全:非線程安全,併發寫入會導致數據損壞,需加鎖或用資料庫替代
  5. 缺乏事務性:寫入中斷會產生殘缺文件,建議寫臨時文件再原子重命名

現代化替代方案

若專案允許引入新依賴,強烈推薦:

  • DOM4J:API 更豐富,XPath 原生支援,性能更優
  • JAXB:定義 POJO 映射 XML,自動處理讀寫,業務代碼零 XML API
  • Jackson XML:XmlMapper 同 JSON 一樣優雅,支援流式

總結

這套工具類展示了 JDOM 處理固定結構 XML 的典型模式:載入→導航→修改→序列化。雖然 JDOM 如今已非主流,但其「具體類 + Collections」的 API 風格對 Java 開發者極其友好,維護舊系統時仍具參考價值。新專案請優先考慮數據綁定框架,將 XML 處理降維為物件操作。

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