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

Java SAX 解析 XML 完整範例:高效率串流式讀取大型 XML

     編輯:Java 相關知識

SAX (Simple API for XML) 是事件驅動的串流式解析器,不將整份 XML 載入記憶體,適合處理大型 XML 檔案。本文提供完整範例,示範如何實作自訂 DefaultHandler 解析包含屬性與巢狀元素的 XML,並映射為 Java 物件清單。

範例 XML 結構 (People.xml)

<People id="1" en="John">
    <Name>張三</Name>
    <Age>25</Age>
</People>
<People id="2" en="Jane">
    <Name>李四</Name>
    <Age>30</Age>
</People>

核心類別

1. 資料模型 People.java

public class People {
    private String id, name, englishName, age;
    // Getter/Setter 略
}

2. 自訂 Handler:SaxHandler.java

class SaxHandler extends DefaultHandler {
    private List<People> peoples = new ArrayList<>();
    private People currentPeople;
    private String currentTag;
    private final String nodeName; // 目標根元素名稱

    public SaxHandler(String nodeName) {
        this.nodeName = nodeName;
    }

    public List<People> getPeoples() { return peoples; }

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

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attrs) {
        currentTag = qName;
        if (qName.equals(nodeName)) {
            currentPeople = new People();
        }
        if (attrs != null && currentPeople != null) {
            for (int i = 0; i < attrs.getLength(); i++) {
                String attrName = attrs.getQName(i);
                String attrVal = attrs.getValue(i);
                if ("id".equals(attrName)) currentPeople.setId(attrVal);
                else if ("en".equals(attrName)) currentPeople.setEnglishName(attrVal);
            }
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) {
        if (currentTag != null && currentPeople != null) {
            String value = new String(ch, start, length).trim();
            if (!value.isEmpty() && !value.equals("\n")) {
                switch (currentTag) {
                    case "Name": currentPeople.setName(value); break;
                    case "Age": currentPeople.setAge(value); break;
                }
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) {
        if (qName.equals(nodeName) && currentPeople != null) {
            peoples.add(currentPeople);
            currentPeople = null;
        }
    }
}

3. 主程式啟動解析

public class SaxXML {
    public static void main(String[] args) {
        File file = new File("e:/People.xml");
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            SaxHandler handler = new SaxHandler("People");
            parser.parse(new FileInputStream(file), handler);

            for (People p : handler.getPeoples()) {
                System.out.println(p.getId() + "\t" + p.getName() + "\t" + p.getEnglishName() + "\t" + p.getAge());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

SAX 關鍵特性與注意事項

特性說明
事件驅動依序觸發 startElement、characters、endElement,需自行管理狀態
低記憶體不建立 DOM 樹,適合超大 XML(百 MB 以上)
單向讀取無法隨機存取或回溯,不支援 XPath
characters 可能分段長文字內容可能多次觸發,需自行累加(本範例簡化處理)
空白文字節點格式化 XML 的縮排換行也會觸發 characters,需 trim() 過濾

效能優化建議

  • 關閉驗證:factory.setValidating(false)(預設關閉)
  • 關閉命名空間感知:factory.setNamespaceAware(false)(若不需命名空間)
  • 重用 SAXParser 實例解析多份結構相同的 XML
  • 避免在 Handler 中建立大量暫存物件,必要時使用物件池

適用場景對比

  • SAX:大型 XML、單向讀取、記憶體受限、只需提取部分資料
  • DOM:小型 XML、需隨機存取/修改、支援 XPath、記憶體充足
  • StAX:拉取式 API,程式碼更直觀,介於 SAX/DOM 之間

此範例展示了 SAX 解析的標準模式,可作為處理大型 XML 資料交換(如報表匯入、日誌分析)的基礎模板。

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