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

Dom4j 實戰完全教程:創建、解析、修改、XPath、輸出格式化與中文編碼

     編輯:Java 相關知識

Dom4j 簡介

Dom4j 是基於 Java 集合框架的開源 XML 操作庫,完整支持 DOM、SAX、JAXP,提供優雅的鏈式 API 與 XPath 查詢。官網:dom4j.org,SourceForge 下載最新版(1.6.1+)。核心依賴:dom4j-x.x.jar + jaxen-x.x.jar(XPath 引擎)。

核心接口體系

所有節點接口繼承自 Node:

  • Document:文檔根
  • Element:元素節點(可含屬性、子元素、文本)
  • Attribute:屬性節點
  • Text / CDATA / Comment:文本類節點
  • Branch:可包含子節點的父接口(Document、Element 實現)

完整實戰代碼:Dom4jDemo

import org.dom4j.*;
import org.dom4j.io.*;
import java.io.*;
import java.util.*;

public class Dom4jDemo {

    /** 1. 創建 XML 文檔 */
    public boolean createXML(String fileName) {
        try {
            Document doc = DocumentHelper.createDocument();
            Element students = doc.addElement("students");
            students.addComment("This is a test for dom4j");

            // 學生 1
            Element stu1 = students.addElement("student");
            stu1.addAttribute("value", "god");
            stu1.addElement("name").setText("finina");
            stu1.addElement("age").setText("25");
            stu1.addElement("sex").setText("male");

            // 學生 2
            Element stu2 = students.addElement("student");
            stu2.addAttribute("value", "cat");
            stu2.addElement("name").setText("fly");
            stu2.addElement("age").setText("17");
            stu2.addElement("sex").setText("female");

            // 團隊信息
            students.addElement("team").addText("05093A");

            // 格式化輸出(關鍵:設置編碼避免中文亂碼)
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("GBK"); // 或 UTF-8
            XMLWriter writer = new XMLWriter(new FileWriter(fileName), format);
            writer.write(doc);
            writer.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /** 2. 修改 XML:屬性更新、節點增刪、文本替換 */
    public boolean modifyXML(String oldFile, String newFile) {
        try {
            SAXReader reader = new SAXReader();
            Document doc = reader.read(new File(oldFile));

            // ① 將所有 student@value="god" 改為 "king"
            for (Attribute attr : (List<Attribute>) doc.selectNodes("/students/student/@value")) {
                if ("god".equals(attr.getValue())) attr.setValue("king");
            }

            // ② 修改 team 文本,並添加子元素 teacher
            Element team = (Element) doc.selectSingleNode("/students/team");
            if (team != null) {
                team.setText("05084A");
                Element teacher = team.addElement("teacher");
                teacher.setText("godfather");
                teacher.addAttribute("skill", "programme");
            }

            // ③ 刪除 age=17 的 age 節點(保護未成年人隱私)
            for (Element stu : (List<Element>) doc.selectNodes("/students/student")) {
                Element age = stu.element("age");
                if (age != null && "17".equals(age.getText())) {
                    stu.remove(age);
                }
            }

            // 保存修改
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("GBK");
            XMLWriter writer = new XMLWriter(new FileWriter(newFile), format);
            writer.write(doc);
            writer.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /** 3. 讀取並遞歸遍歷 XML */
    public void readXML(String fileName) {
        try {
            SAXReader reader = new SAXReader();
            Document doc = reader.read(new File(fileName));
            traverse(doc.getRootElement());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void traverse(Element element) {
        for (Iterator it = element.elementIterator(); it.hasNext(); ) {
            Element el = (Element) it.next();
            if (!el.getTextTrim().isEmpty()) {
                System.out.println(el.getName() + " 節點的值是 " + el.getText());
            } else {
                System.out.println(el.getName() + " 節點");
            }
            for (Iterator ait = el.attributeIterator(); ait.hasNext(); ) {
                Attribute attr = (Attribute) ait.next();
                System.out.println(el.getName() + " 節點的屬性 " + attr.getName() + " 的值是 " + attr.getValue());
            }
            traverse(el); // 遞歸子元素
        }
    }

    /** 主方法演示 */
    public static void main(String[] args) {
        Dom4jDemo demo = new Dom4jDemo();
        String file = "dom4jDemo.xml";
        String newFile = "new_dom4jDemo.xml";

        System.out.println("創建 " + file + " ...");
        if (demo.createXML(file)) System.out.println("創建成功!");

        System.out.println("修改並另存為 " + newFile + " ...");
        if (demo.modifyXML(file, newFile)) System.out.println("修改成功!");

        System.out.println("讀取原文件:");
        demo.readXML(file);
        System.out.println("讀取新文件:");
        demo.readXML(newFile);
    }
}

關鍵技術點總結

1. 讀取策略

  • SAXReader:事件驅動,適合大文件(默認)。
  • DOMReader:樹模型,適合需隨機訪問場景。
  • 支持 File、InputStream、URL、Reader 多種來源。

2. 遍歷三種方式

  1. 迭代器:elementIterator() / attributeIterator(),最常用。
  2. 遞歸:配合 nodeCount() + node(i),適合深度處理。
  3. Visitor 模式:實現 Visitor 接口(或繼承 VisitorSupport),調用 node.accept(visitor) 自動遍歷全樹,代碼最乾淨。

3. XPath 強力查詢

List nodes = doc.selectNodes("//foo/bar");           // 多節點
Node node = doc.selectSingleNode("//foo/bar/author"); // 單節點
String name = node.valueOf("@name");                  // 直接取屬性值

// 實例:提取 XHTML 所有鏈接
List links = doc.selectNodes("//a/@href");

4. 字符串 ⇄ XML 雙向轉換

// XML → String
String xml = document.asXML();

// String → XML
Document doc = DocumentHelper.parseText("James");

5. XSLT 轉換

TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(stylesheet));
DocumentSource source = new DocumentSource(document);
DocumentResult result = new DocumentResult();
transformer.transform(source, result);
Document transformed = result.getDocument();

6. 輸出格式化與中文編碼

必須設置編碼,否則中文輸出亂碼或無法解析:

OutputFormat format = OutputFormat.createPrettyPrint(); // 縮進美化
// OutputFormat format = OutputFormat.createCompactFormat(); // 壓縮無換行
format.setEncoding("GBK"); // 或 UTF-8, ISO-8859-1
XMLWriter writer = new XMLWriter(new FileWriter(file), format);
writer.write(document);

常見坑與最佳實踐

  • 編碼一致性:XML 聲明、Java 文件編碼、OutputFormat 編碼、讀取時系統默認編碼,四者必須一致。
  • 大文件處理:使用 SAXReader + ElementHandler 流式處理,避免 DOM 模型佔用大量內存。
  • 命名空間:XPath 查詢帶命名空間時需註冊 NamespaceContext。
  • 線程安全:Document 非線程安全,多線程環境下勿共享實例。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved