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

Java XML 解析實戰:DOM、SAX 與 dom4j 完整對比與代碼範例

     編輯:Java 相關知識

前言

XML 作為通用資料交換格式,在 Java 體系中擁有豐富的解析生態。本文系統對比 DOM、SAX、dom4j 三大主流方案,提供完整可執行代碼範例,幫助開發者根據場景選擇最適合的解析策略。

核心解析模型對比

維度DOM (Document Object Model)SAX (Simple API for XML)dom4j
原理 一次性載入整份文檔建立樹結構 事件驅動流式解析,不建立樹 封裝 DOM/SAX,支援 XPath、XSLT
記憶體佔用 高(整份文檔駐留記憶體) 極低(僅當前節點) 中等(視使用模式)
操作靈活度 支援增刪改查、隨機訪問 唯讀、單向流式 完整支援寫入、XPath 查詢
適用場景 小檔案、需多次操作、修改 XML 大檔案、嵌入式、單次讀取 企業級開發、複雜 XML 處理
Android 推薦度 低(記憶體受限) 高(官方推薦) 中(需引入第三方 jar)

dom4j 實戰:生成與解析 XML

Maven 依賴

<dependency>
    <groupId>org.dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>2.1.4</version>
</dependency>
<!-- JAXP 相容 -->
<dependency>
    <groupId>xml-apis</groupId>
    <artifactId>xml-apis</artifactId>
    <version>1.4.01</version>
</dependency>

範例 1:程式化生成 XML

public class Dom4jCreateDemo {
    public static void main(String[] args) throws Exception {
        // 1. 建立 Document 與根元素
        Document document = DocumentHelper.createDocument();
        Element root = document.addElement("students");

        // 2. 新增學生節點(支援屬性、巢狀結構)
        Element stu1 = root.addElement("student")
                .addAttribute("id", "1001")
                .addAttribute("name", "張三");
        stu1.addElement("course").addAttribute("name", "數學").setText("95");
        stu1.addElement("course").addAttribute("name", "英文").setText("88");

        Element stu2 = root.addElement("student")
                .addAttribute("id", "1002")
                .addAttribute("name", "李四");
        stu2.addElement("course").addAttribute("name", "數學").setText("90");
        stu2.addElement("course").addAttribute("name", "英文").setText("92");

        // 3. 格式化輸出至檔案
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-8");
        XMLWriter writer = new XMLWriter(new FileOutputStream("students.xml"), format);
        writer.write(document);
        writer.close();

        System.out.println("XML 生成完成");
    }
}

輸出結果:

<?xml version="1.0" encoding="UTF-8"?>
<students>
  <student id="1001" name="張三">
    <course name="數學">95</course>
    <course name="英文">88</course>
  </student>
  <student id="1002" name="李四">
    <course name="數學">90</course>
    <course name="英文">92</course>
  </student>
</students>

範例 2:SAXReader 解析 + XPath 查詢

public class Dom4jParseDemo {
    public static void main(String[] args) throws Exception {
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File("students.xml"));
        Element root = doc.getRootElement();

        // 1. 遍歷所有學生
        for (Element student : root.elements("student")) {
            String id = student.attributeValue("id");
            String name = student.attributeValue("name");
            System.out.printf("學生: %s (%s)%n", name, id);

            // 2. XPath 查詢該學生所有課程
            List courses = student.selectNodes("course");
            for (Element c : courses) {
                System.out.printf("  - %s: %s%n", 
                    c.attributeValue("name"), c.getText());
            }
        }

        // 3. 直接 XPath 定位:所有數學成績 > 90 的學生
        List topMath = doc.selectNodes("//student[course[@name='數學'] > 90]");
        System.out.println("\n數學優秀學生:");
        for (Element s : topMath) {
            System.out.println("  " + s.attributeValue("name"));
        }
    }
}

原生 SAX 解析:事件驅動模式

適合超大檔案、記憶體極度受限環境(如 Android)。核心流程:

  1. 建立 SAXParserFactory → SAXParser
  2. 實作 DefaultHandler 覆寫四大回調方法
  3. 呼叫 parse(InputStream, handler)

完整 SAX 解析範例

public class SaxParserDemo extends DefaultHandler {
    private List persons = new ArrayList<>();
    private Person currentPerson;
    private String currentTag;

    @Override
    public void startDocument() {
        persons = new ArrayList<>();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attrs) {
        currentTag = localName;
        if ("person".equals(localName)) {
            currentPerson = new Person();
            currentPerson.setId(attrs.getValue("id"));
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) {
        if (currentPerson == null) return;
        String value = new String(ch, start, length).trim();
        if (value.isEmpty()) return;
        switch (currentTag) {
            case "name": currentPerson.setName(value); break;
            case "age": currentPerson.setAge(value); break;
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) {
        if ("person".equals(localName) && currentPerson != null) {
            persons.add(currentPerson);
            currentPerson = null;
        }
        currentTag = "";
    }

    public List parse(InputStream is) throws Exception {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();
        parser.parse(is, this);
        return persons;
    }

    // 測試主程式
    public static void main(String[] args) throws Exception {
        try (InputStream is = new FileInputStream("persons.xml")) {
            List list = new SaxParserDemo().parse(is);
            list.forEach(p -> System.out.println(p.getId() + " " + p.getName() + " " + p.getAge()));
        }
    }
}

DOM 解析:隨機訪問與修改

public class DomParserDemo {
    public static void main(String[] args) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(new File("students.xml"));

        // 1. 讀取
        NodeList students = doc.getElementsByTagName("student");
        for (int i = 0; i < students.getLength(); i++) {
            Element stu = (Element) students.item(i);
            System.out.println(stu.getAttribute("name"));
        }

        // 2. 修改:將第一位學生姓名改為 "王五"
        Element first = (Element) students.item(0);
        first.setAttribute("name", "王五");

        // 3. 新增節點
        Element newStu = doc.createElement("student");
        newStu.setAttribute("id", "1003");
        newStu.setAttribute("name", "趙六");
        doc.getDocumentElement().appendChild(newStu);

        // 4. 寫回檔案
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.transform(new DOMSource(doc), new StreamResult(new File("students_modified.xml")));
    }
}

選型決策樹

需要修改/寫入 XML?
├─ 是 → 檔案 < 50MB? → dom4j / DOM
└─ 否 → 僅讀取?
       ├─ 檔案 > 100MB / Android / 記憶體受限 → SAX
       ├─ 需 XPath 複雜查詢 → dom4j
       └─ 簡單遍歷、標準 API 偏好 → DOM / SAX

總結

  • dom4j:企業開發首選,API 友善、支援 XPath、寫入方便
  • SAX:大檔案、串流、低記憶體、Android 官方推薦
  • DOM:小檔案、需隨機訪問/修改、零依賴

實務上常組合使用:SAX 快速篩選大檔案關鍵片段 → dom4j 精細處理片段。

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