The method parse(InputStream, HandlerBase) in the type SAXParser
is not applicable for the arguments (InputStream, MyHandler)
SAXParser.parse() 要求第二個參數為 DefaultHandler(或舊版 HandlerBase)子類別。自訂 MyHandler 必須繼承 DefaultHandler 並覆寫所需回調方法。
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.*;
public class MyHandler extends DefaultHandler { // 關鍵:繼承 DefaultHandler
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
// 元素開始:
System.out.println("開始元素:" + qName);
for (int i = 0; i < attributes.getLength(); i++) {
System.out.println(" 屬性:" + attributes.getQName(i) + "=" + attributes.getValue(i));
}
}
@Override
public void endElement(String uri, String localName, String qName) {
// 元素結束:
System.out.println("結束元素:" + qName);
}
@Override
public void characters(char[] ch, int start, int length) {
// 元素文字內容
String content = new String(ch, start, length).trim();
if (!content.isEmpty()) System.out.println("文字內容:" + content);
}
}
// 使用範例
public class SaxDemo {
public static void main(String[] args) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
MyHandler handler = new MyHandler();
parser.parse(new FileInputStream("data.xml"), handler); // 現在型別匹配
}
}
| 方法 | 觸發時機 | 典型用途 |
|---|---|---|
startDocument() | 文檔開始 | 初始化資料結構 |
startElement(uri, localName, qName, attrs) | 遇到開始標籤 | 建立物件、推入堆疊、讀取屬性 |
characters(ch, start, length) | 元素文字內容 | 累加文字(可能多次呼叫) |
endElement(uri, localName, qName) | 遇到結束標籤 | 完成物件、彈出堆疊、加入集合 |
endDocument() | 文檔結束 | 最終處理、輸出結果 |
<books>
<book id="1">
<title>Effective Java</title>
<author>Joshua Bloch</author>
</book>
</books>
public class BookHandler extends DefaultHandler {
private List<Book> books = new ArrayList<>();
private Book currentBook;
private StringBuilder currentText = new StringBuilder();
@Override
public void startElement(String uri, String localName, String qName, Attributes attrs) {
currentText.setLength(0);
if ("book".equals(qName)) {
currentBook = new Book();
currentBook.setId(attrs.getValue("id"));
}
}
@Override
public void characters(char[] ch, int start, int length) {
currentText.append(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) {
String text = currentText.toString().trim();
if (currentBook != null) {
switch (qName) {
case "title": currentBook.setTitle(text); break;
case "author": currentBook.setAuthor(text); break;
case "book": books.add(currentBook); currentBook = null; break;
}
}
}
public List<Book> getBooks() { return books; }
}
| 特性 | SAX (事件驅動) | DOM (樹模型) |
|---|---|---|
| 記憶體 | O(1) 流式,適合大檔 | O(N) 全載入記憶體 |
| 速度 | 快,單次掃描 | 較慢,建樹開銷 |
| 隨機存取 | 不支援 | 支援 XPath、修改 |
| 適用場景 | 讀取大型 XML、提取特定資訊 | 需修改/多次查詢、小檔案 |
自訂 SAX Handler 必須繼承 DefaultHandler(或實作 ContentHandler 介面)。核心回調:startElement、characters、endElement。注意 characters 可能分段呼叫,需用 StringBuilder 累加。大檔案優先選 SAX,需修改結構選 DOM。