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

Java 構建與生成 XML 簡明教程(dom4j)

     編輯:Java 程式設計入門

前言

Java 中處理 XML 常用 DOM、SAX、JDOM、dom4j。其中 dom4j 以 API 簡潔、效能優異、支援 XPath、廣泛應用於 Hibernate、Spring 等框架,是首選庫。本文示範如何快速構建 XML 文件並輸出。

環境準備

Maven 依賴


<dependency>
    <groupId>org.dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>2.1.4</version>
</dependency>
<!-- XPath 支援需額外引入 -->
<dependency>
    <groupId>org.jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.2.0</version>
</dependency>

核心匯入


import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

XML 構建五步驟

步驟 1:建立 Document 與根元素


// 建立空文件
Document document = DocumentHelper.createDocument();

// 建立根元素並加入文件
Element root = document.addElement("return");

步驟 2:新增子元素


// 在根元素下新增子元素
Element returnValue = root.addElement("returnvalue");
Element returnInfo = root.addElement("returninfo");

步驟 3:設定元素文本內容


// 方式一:建立後設定文本
returnValue.addText("false");
returnInfo.addText("get-session-fail");

// 方式二:鏈式呼叫,建立同時設定文本
root.addElement("id").addText("12345");
root.addElement("timestamp").addText(String.valueOf(System.currentTimeMillis()));

步驟 4:處理特殊情況


// 避免 null 值導致例外:加上空字串
String nullableValue = getNullableString();
root.addElement("optional").addText(nullableValue + "");

// 非字串類型轉換
int id = 1;
root.addElement("id").addText(id + "");           // 整數
root.addElement("price").addText(99.9 + "");      // 浮點數
root.addElement("active").addText(true + "");     // 布林值

// CDATA 區段(包含特殊字元)
Element content = root.addElement("content");
content.addCDATA("");

// 設定屬性
Element user = root.addElement("user");
user.addAttribute("id", "1001");
user.addAttribute("role", "admin");
user.addText("John Doe");

步驟 5:輸出 XML


// 輸出為字串
String xmlString = document.asXML();
System.out.println(xmlString);

// 輸出為檔案(格式化)
try (FileWriter fw = new FileWriter("output.xml")) {
    OutputFormat format = OutputFormat.createPrettyPrint();
    format.setEncoding("UTF-8");
    XMLWriter writer = new XMLWriter(fw, format);
    writer.write(document);
    writer.flush();
}

// 輸出到 HTTP 響應(Servlet)
response.setContentType("text/xml; charset=UTF-8");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(response.getWriter(), format);
writer.write(document);
writer.flush();

完整範例:生成訂單 XML


public class OrderXmlGenerator {
    public static void main(String[] args) throws Exception {
        Document doc = DocumentHelper.createDocument();
        Element order = doc.addElement("order");
        order.addAttribute("version", "1.0");
        order.addAttribute("orderNo", "ORD-20240115-001");
        
        // 客戶資訊
        Element customer = order.addElement("customer");
        customer.addElement("id").addText("CUST-1001");
        customer.addElement("name").addText("張三");
        customer.addElement("email").addText("zhangsan@example.com");
        customer.addElement("phone").addText("0912-345-678");
        
        // 商品清單
        Element items = order.addElement("items");
        addItem(items, "ITEM-001", "筆記型電腦", 1, 35000);
        addItem(items, "ITEM-002", "無線滑鼠", 2, 590);
        addItem(items, "ITEM-003", "機械鍵盤", 1, 2800);
        
        // 總計
        Element total = order.addElement("total");
        total.addElement("subtotal").addText("41780");
        total.addElement("discount").addText("0");
        total.addElement("shipping").addText("120");
        total.addElement("grandTotal").addText("41900");
        
        // 狀態與時間
        order.addElement("status").addText("CONFIRMED");
        order.addElement("createdAt").addText("2024-01-15T10:30:00+08:00");
        
        // 輸出
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-8");
        XMLWriter writer = new XMLWriter(System.out, format);
        writer.write(doc);
        writer.flush();
    }
    
    private static void addItem(Element parent, String id, String name, int qty, int price) {
        Element item = parent.addElement("item");
        item.addAttribute("id", id);
        item.addElement("name").addText(name);
        item.addElement("quantity").addText(String.valueOf(qty));
        item.addElement("unitPrice").addText(String.valueOf(price));
        item.addElement("subtotal").addText(String.valueOf(qty * price));
    }
}

輸出結果


<?xml version="1.0" encoding="UTF-8"?>
<order version="1.0" orderNo="ORD-20240115-001">
  <customer>
    <id>CUST-1001</id>
    <name>張三</name>
    <email>zhangsan@example.com</email>
    <phone>0912-345-678</phone>
  </customer>
  <items>
    <item id="ITEM-001">
      <name>筆記型電腦</name>
      <quantity>1</quantity>
      <unitPrice>35000</unitPrice>
      <subtotal>35000</subtotal>
    </item>
    <item id="ITEM-002">
      <name>無線滑鼠</name>
      <quantity>2</quantity>
      <unitPrice>590</unitPrice>
      <subtotal>1180</subtotal>
    </item>
    <item id="ITEM-003">
      <name>機械鍵盤</name>
      <quantity>1</quantity>
      <unitPrice>2800</unitPrice>
      <subtotal>2800</subtotal>
    </item>
  </items>
  <total>
    <subtotal>41780</subtotal>
    <discount>0</discount>
    <shipping>120</shipping>
    <grandTotal>41900</grandTotal>
  </total>
  <status>CONFIRMED</status>
  <createdAt>2024-01-15T10:30:00+08:00</createdAt>
</order>

進階技巧

1. 命名空間支援


Document doc = DocumentHelper.createDocument();
Element root = doc.addElement("root", "https://example.com/ns");
root.addNamespace("ns", "https://example.com/ns");
root.addNamespace("xsi", "https://www.w3.org/2001/XMLSchema-instance");
root.addAttribute("schemaLocation", "https://example.com/ns schema.xsd", 
                  doc.getNamespaceForPrefix("xsi"));

2. 從 Java 物件自動生成 XML(反射)


public void objectToXml(Object obj, Element parent) {
    Class clazz = obj.getClass();
    for (Field field : clazz.getDeclaredFields()) {
        field.setAccessible(true);
        try {
            Object value = field.get(obj);
            if (value != null) {
                Element child = parent.addElement(field.getName());
                if (isPrimitiveOrWrapper(field.getType()) || value instanceof String) {
                    child.addText(value.toString());
                } else if (value instanceof Collection) {
                    for (Object item : (Collection) value) {
                        Element itemEl = child.addElement("item");
                        objectToXml(item, itemEl);
                    }
                } else {
                    objectToXml(value, child);  // 遞迴處理巢狀物件
                }
            }
        } catch (IllegalAccessException e) { /* 忽略 */ }
    }
}

3. 串流式寫入大型 XML(低記憶體)


// dom4j 不直接支援 StAX 輸出,大檔案建議用標準 javax.xml.stream
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter(new FileOutputStream("large.xml"));
writer.writeStartDocument("UTF-8", "1.0");
writer.writeStartElement("root");
// 循環寫入大量資料...
writer.writeEndElement();
writer.writeEndDocument();
writer.close();

常見問題

問題原因解決
addText(null) 拋出 NPEdom4j 不接受 null使用 value + "" 或 Objects.toString(value, "")
中文輸出亂碼編碼不一致設定 format.setEncoding("UTF-8")、確保檔案/輸出流編碼一致
特殊字元 (< > &) 未轉義直接加入文本使用 addText() 自動轉義、或 addCDATA() 包含原始內容
記憶體溢出巨大 XML 全載入記憶體改用 StAX 串流寫入、或分批生成
XPath 查詢失效缺少 jaxen.jar加入 jaxen 依賴

結語

dom4j 以直觀的鏈式 API 讓 Java 構建 XML 變得簡單高效。掌握 DocumentHelper、Element、OutputFormat、XMLWriter 核心類別,配合屬性、CDATA、命名空間等進階功能,即可應對各種 XML 生成需求。大型檔案場景下請改用 StAX 串流式寫入避免記憶體壓力。

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