Webサービスを開発していると、XML(Extensible Markup Language)形式のデータを扱うことがよくあります。
設定ファイル、データ交換、Webサービスの応答など、XMLは様々な場面で使われています。
でも、こんな経験はありませんか?
- 数百MBの巨大なXMLファイルを開こうとしたら、メモリ不足で失敗した
 - XMLを全部読み込むのに時間がかかりすぎる
 - 必要な情報は一部なのに、全体を読み込まないといけない
 
そんな問題を解決するのがSAX(Simple API for XML)です。
SAXは、XMLファイルを少しずつ読み進めながら処理する方式で、メモリを節約しながら高速に動作します。この記事では、SAXの仕組みや使い方について、初心者の方にも分かるように詳しく解説していきます。
XML解析の基礎知識
XMLとは?
まず、XMLの基本をおさらいしましょう。
XML(Extensible Markup Language)は、データを構造化して記述するためのマークアップ言語です。
XMLの例:書籍リスト
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
    <book id="001">
        <title>プログラミング入門</title>
        <author>山田太郎</author>
        <price>2500</price>
        <year>2024</year>
    </book>
    <book id="002">
        <title>データベース設計</title>
        <author>佐藤花子</author>
        <price>3200</price>
        <year>2023</year>
    </book>
</bookstore>
特徴:
- タグで囲まれた階層構造
 - 人間にも機械にも読みやすい
 - 自由に構造を定義できる
 
なぜXML解析が必要?
プログラムでXMLを扱うには、解析(パース)が必要です。
解析の目的:
- XMLの構造を理解する
 - 必要なデータを取り出す
 - データを加工・変換する
 - エラーをチェックする
 
XML解析の2つのアプローチ
XML解析には、大きく分けて2つの方法があります。
1. DOM(Document Object Model)
- XML全体をメモリに読み込む
 - ツリー構造を構築
 - どこからでもアクセス可能
 
2. SAX(Simple API for XML)
- 順番に読み進める
 - イベント駆動で処理
 - メモリ効率が良い
 
本記事のテーマはSAXです。
SAXとは?基本を理解しよう
SAXの定義
SAX(Simple API for XML)は、XMLファイルをイベント駆動方式で解析するAPIです。
開発の歴史:
- 1998年に登場
 - David Megginson氏が中心となって開発
 - Java向けに設計されたが、多くの言語に実装された
 
「Simple」の意味:
名前に「Simple」とありますが、これは「シンプルな実装」という意味で、実際には概念的にはDOMより理解しにくいかもしれません。
イベント駆動方式とは?
SAXの最大の特徴がイベント駆動です。
イメージ:本を読む人
XMLファイルを本に例えると:
DOM方式:
本を全部読んでから、内容を思い出しながら作業する
→ 全ページを記憶する必要がある(メモリ大量消費)
SAX方式:
本を1ページずつ読みながら、気になる部分をメモする
→ 今読んでいるページだけ覚えていればOK(メモリ節約)
イベントの流れ
SAXは、XMLを読み進めながら、様々な「イベント」を発生させます。
例:簡単なXML
<book>
    <title>プログラミング入門</title>
</book>
発生するイベント:
1. ドキュメント開始
2. 要素開始: <book>
3. 要素開始: <title>
4. テキスト: "プログラミング入門"
5. 要素終了: </title>
6. 要素終了: </book>
7. ドキュメント終了
プログラムは、これらのイベントに反応して処理を行います。
料理に例えると
分かりやすく料理で例えてみましょう。
DOM方式:
1. レシピ全体を読む
2. すべての材料を準備
3. 全工程を頭に入れてから調理開始
SAX方式:
1. レシピを1行読む → その作業をする
2. 次の行を読む → その作業をする
3. 繰り返し
SAXは「読みながら作業する」スタイルなんです。
DOMとSAXの違い
2つの解析方法を詳しく比較してみましょう。
DOMの仕組み
DOM(Document Object Model)は、XML全体をツリー構造としてメモリに読み込みます。
動作:
XMLファイル
    ↓ 全体を読み込む
メモリ内のツリー構造
    ↓ 自由にアクセス
プログラムで処理
イメージ:
bookstore
├── book (id="001")
│   ├── title: "プログラミング入門"
│   ├── author: "山田太郎"
│   ├── price: "2500"
│   └── year: "2024"
└── book (id="002")
    ├── title: "データベース設計"
    ├── author: "佐藤花子"
    ├── price: "3200"
    └── year: "2023"
このツリー全体がメモリに載ります。
SAXの仕組み
SAXは、XMLを先頭から順番に読み、イベントを発生させます。
動作:
XMLファイル
    ↓ 少しずつ読む
イベント発生
    ↓ イベントごとに処理
プログラムで処理
特徴:
- ファイル全体はメモリに載らない
 - 読んだ部分だけ処理して、すぐに忘れる
 - 一方通行(戻れない)
 
比較表
| 項目 | DOM | SAX | 
|---|---|---|
| メモリ使用量 | 大きい(全体を保持) | 小さい(少しずつ処理) | 
| 処理速度 | 遅い(全体を読み込むまで待つ) | 速い(すぐに処理開始) | 
| アクセス方式 | ランダムアクセス可能 | 順次アクセスのみ | 
| 使いやすさ | 簡単(ツリー構造が直感的) | やや難しい(イベント処理) | 
| XML生成 | 可能 | 不可能(読み込み専用) | 
| 大きなファイル | 不向き(メモリ不足の危険) | 向いている | 
| 複雑な処理 | 向いている(何度でもアクセス) | 不向き(一度しか読めない) | 
それぞれが適している場面
DOMが向いている:
- 小〜中サイズのXML(数MB以下)
 - XMLの複数箇所にアクセスする必要がある
 - XMLを編集・生成する
 - 構造が複雑で、親子関係を辿る必要がある
 
SAXが向いている:
- 大きなXMLファイル(数十MB〜数GB)
 - 必要な情報だけを抽出する
 - 順番に処理すればOK
 - メモリが限られている環境
 - ストリーミング処理
 
SAXのイベント一覧
SAXで発生する主なイベントを見ていきましょう。
ドキュメントレベルのイベント
startDocument(ドキュメント開始)
- XML解析の開始時に1回だけ発生
 - 初期化処理などに使う
 
endDocument(ドキュメント終了)
- XML解析の終了時に1回だけ発生
 - 後処理、結果の出力などに使う
 
要素レベルのイベント
startElement(要素開始)
<tag>のような開始タグを読んだとき- 要素名と属性情報が渡される
 
endElement(要素終了)
</tag>のような終了タグを読んだとき- 要素名が渡される
 
テキストレベルのイベント
characters(文字データ)
- タグとタグの間のテキスト
 - 複数回に分けて呼ばれることもある
 
その他のイベント
ignorableWhitespace(無視できる空白)
- 改行やインデントなどの空白文字
 
processingInstruction(処理命令)
<?xml ... ?>のような処理命令
skippedEntity(スキップされたエンティティ)
- エンティティ参照がスキップされた
 
warning、error、fatalError
- 警告やエラーが発生したとき
 
SAXのメリット
SAXを使う利点を詳しく見ていきましょう。
1. メモリ効率が非常に良い
最大のメリット
SAXは、XMLファイル全体をメモリに読み込みません。
例:1GBのXMLファイル
DOM:
- 1GB以上のメモリを消費(ツリー構造のオーバーヘッド)
 - メモリ不足でクラッシュの危険
 
SAX:
- 数MB程度のメモリで処理可能
 - どんなに大きなファイルでも安定
 
2. 処理が速い
すぐに処理を開始できる
DOMは全体を読み込んでから処理しますが、SAXは読みながら処理します。
例:10万行のXML
DOM:
読み込み完了まで待つ(10秒)
    ↓
処理開始
SAX:
読み込み開始 → すぐに処理開始
並行して実行
3. ストリーミング処理が可能
ネットワーク越しのXMLにも対応
ファイル全体をダウンロードする前に、処理を開始できます。
ネットワーク → 受信しながら解析 → 処理
リアルタイム性が求められる場合に有効です。
4. 単純な処理に最適
必要な情報だけを抽出
複雑な操作は不要で、特定のデータを取り出すだけなら、SAXが最適です。
例:書籍タイトルだけを抽出
if (elementName.equals("title")) {
    // タイトルのテキストを保存
}
5. メモリリークのリスクが低い
構造をメモリに保持しない
DOMではツリー全体がメモリに残りますが、SAXは読んだらすぐに忘れるため、メモリリークのリスクが低いです。
SAXのデメリット
良いことばかりではありません。いくつかの制約があります。
1. 複雑な処理が難しい
一方通行の制約
一度読んだ部分には戻れません。
できないこと:
- 親要素の情報を後から参照
 - 前後の要素を比較
 - ランダムアクセス
 
対策:
必要な情報は、変数に保存しておく必要があります。
2. 状態管理が必要
どこを読んでいるか追跡が必要
イベントは順番に来るだけなので、「今どの要素の中にいるか」を自分で管理する必要があります。
// 階層を追跡する例
Stack<String> elementStack = new Stack<>();
public void startElement(...) {
    elementStack.push(elementName);  // スタックに追加
}
public void endElement(...) {
    elementStack.pop();  // スタックから削除
}
3. コードが複雑になりがち
イベント駆動のコードは分かりにくい
DOMのような直感的なツリー操作ではないため、コードが複雑になることがあります。
DOM(簡潔):
NodeList books = doc.getElementsByTagName("book");
for (int i = 0; i < books.getLength(); i++) {
    Element book = (Element) books.item(i);
    String title = book.getElementsByTagName("title").item(0).getTextContent();
}
SAX(複雑):
boolean inTitle = false;
StringBuilder titleText = new StringBuilder();
public void startElement(...) {
    if (localName.equals("title")) {
        inTitle = true;
    }
}
public void characters(...) {
    if (inTitle) {
        titleText.append(new String(ch, start, length));
    }
}
public void endElement(...) {
    if (localName.equals("title")) {
        System.out.println("Title: " + titleText.toString());
        titleText.setLength(0);
        inTitle = false;
    }
}
4. XMLの編集・生成ができない
読み取り専用
SAXは解析(読み込み)専用で、XMLを編集したり、新しく生成したりすることはできません。
XMLを生成したい場合:
別のAPIを使う必要があります(StAXやDOMなど)。
5. エラーからの回復が難しい
途中でエラーが起きたら
XML全体を把握していないため、エラーが起きた場合の対処が難しいです。
SAXの実装:プログラミング例
実際にSAXを使ってプログラムを書いてみましょう。
Javaでの実装
JavaのSAXは、org.xml.saxパッケージで提供されています。
基本的な使い方:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
// SAXハンドラーを作成
class BookHandler extends DefaultHandler {
    private boolean inTitle = false;
    private boolean inAuthor = false;
    private boolean inPrice = false;
    private StringBuilder currentText = new StringBuilder();
    // ドキュメント開始
    @Override
    public void startDocument() throws SAXException {
        System.out.println("=== XML解析開始 ===");
    }
    // 要素開始
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) 
            throws SAXException {
        currentText.setLength(0);  // テキストをクリア
        if (qName.equals("book")) {
            String id = attributes.getValue("id");
            System.out.println("\n書籍ID: " + id);
        } else if (qName.equals("title")) {
            inTitle = true;
        } else if (qName.equals("author")) {
            inAuthor = true;
        } else if (qName.equals("price")) {
            inPrice = true;
        }
    }
    // テキストデータ
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        currentText.append(new String(ch, start, length));
    }
    // 要素終了
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (qName.equals("title") && inTitle) {
            System.out.println("  タイトル: " + currentText.toString().trim());
            inTitle = false;
        } else if (qName.equals("author") && inAuthor) {
            System.out.println("  著者: " + currentText.toString().trim());
            inAuthor = false;
        } else if (qName.equals("price") && inPrice) {
            System.out.println("  価格: " + currentText.toString().trim() + "円");
            inPrice = false;
        }
    }
    // ドキュメント終了
    @Override
    public void endDocument() throws SAXException {
        System.out.println("\n=== XML解析終了 ===");
    }
    // エラー処理
    @Override
    public void error(SAXParseException e) throws SAXException {
        System.err.println("エラー: " + e.getMessage());
    }
}
// メインクラス
public class SAXExample {
    public static void main(String[] args) {
        try {
            // SAXパーサーを作成
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            // ハンドラーを作成
            BookHandler handler = new BookHandler();
            // XMLファイルを解析
            parser.parse(new File("books.xml"), handler);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
出力例:
=== XML解析開始 ===
書籍ID: 001
  タイトル: プログラミング入門
  著者: 山田太郎
  価格: 2500円
書籍ID: 002
  タイトル: データベース設計
  著者: 佐藤花子
  価格: 3200円
=== XML解析終了 ===
Pythonでの実装
Pythonでは、xml.saxモジュールを使います。
import xml.sax
class BookHandler(xml.sax.ContentHandler):
    """SAXハンドラークラス"""
    def __init__(self):
        self.current_element = ""
        self.current_text = ""
        self.in_title = False
        self.in_author = False
        self.in_price = False
    def startDocument(self):
        """ドキュメント開始"""
        print("=== XML解析開始 ===")
    def startElement(self, name, attrs):
        """要素開始"""
        self.current_element = name
        self.current_text = ""
        if name == "book":
            book_id = attrs.get("id", "")
            print(f"\n書籍ID: {book_id}")
        elif name == "title":
            self.in_title = True
        elif name == "author":
            self.in_author = True
        elif name == "price":
            self.in_price = True
    def characters(self, content):
        """テキストデータ"""
        self.current_text += content
    def endElement(self, name):
        """要素終了"""
        text = self.current_text.strip()
        if name == "title" and self.in_title:
            print(f"  タイトル: {text}")
            self.in_title = False
        elif name == "author" and self.in_author:
            print(f"  著者: {text}")
            self.in_author = False
        elif name == "price" and self.in_price:
            print(f"  価格: {text}円")
            self.in_price = False
        self.current_text = ""
    def endDocument(self):
        """ドキュメント終了"""
        print("\n=== XML解析終了 ===")
# メイン処理
if __name__ == "__main__":
    # パーサーを作成
    parser = xml.sax.make_parser()
    # ハンドラーを設定
    handler = BookHandler()
    parser.setContentHandler(handler)
    # XMLファイルを解析
    try:
        parser.parse("books.xml")
    except Exception as e:
        print(f"エラー: {e}")
C#での実装
C#では、System.Xml.XmlReaderを使うのが一般的です(厳密にはSAXではないですが、同じイベント駆動方式です)。
using System;
using System.Xml;
class SAXExample
{
    static void Main()
    {
        Console.WriteLine("=== XML解析開始 ===");
        try
        {
            using (XmlReader reader = XmlReader.Create("books.xml"))
            {
                string currentElement = "";
                while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Element:
                            currentElement = reader.Name;
                            if (currentElement == "book")
                            {
                                string id = reader.GetAttribute("id");
                                Console.WriteLine($"\n書籍ID: {id}");
                            }
                            break;
                        case XmlNodeType.Text:
                            string text = reader.Value.Trim();
                            if (currentElement == "title")
                            {
                                Console.WriteLine($"  タイトル: {text}");
                            }
                            else if (currentElement == "author")
                            {
                                Console.WriteLine($"  著者: {text}");
                            }
                            else if (currentElement == "price")
                            {
                                Console.WriteLine($"  価格: {text}円");
                            }
                            break;
                        case XmlNodeType.EndElement:
                            currentElement = "";
                            break;
                    }
                }
            }
            Console.WriteLine("\n=== XML解析終了 ===");
        }
        catch (Exception e)
        {
            Console.WriteLine($"エラー: {e.Message}");
        }
    }
}
実践例:大きなXMLファイルの処理
実際の使用例を見てみましょう。
例1:ログファイルから特定情報を抽出
シナリオ:
1GBの巨大なログXMLから、エラーメッセージだけを抽出する
XMLの構造:
<logs>
    <entry level="INFO">
        <timestamp>2024-01-01 10:00:00</timestamp>
        <message>システム起動</message>
    </entry>
    <entry level="ERROR">
        <timestamp>2024-01-01 10:05:00</timestamp>
        <message>データベース接続エラー</message>
    </entry>
    <!-- ... 数百万件のエントリ ... -->
</logs>
SAXでの処理:
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
class LogEntry {
    String timestamp;
    String message;
    public LogEntry(String timestamp, String message) {
        this.timestamp = timestamp;
        this.message = message;
    }
    @Override
    public String toString() {
        return timestamp + " - " + message;
    }
}
class ErrorLogHandler extends DefaultHandler {
    private List<LogEntry> errorLogs = new ArrayList<>();
    private boolean isError = false;
    private boolean inTimestamp = false;
    private boolean inMessage = false;
    private StringBuilder currentText = new StringBuilder();
    private String currentTimestamp = "";
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        currentText.setLength(0);
        if (qName.equals("entry")) {
            String level = attributes.getValue("level");
            isError = "ERROR".equals(level);
        } else if (qName.equals("timestamp")) {
            inTimestamp = true;
        } else if (qName.equals("message")) {
            inMessage = true;
        }
    }
    @Override
    public void characters(char[] ch, int start, int length) {
        currentText.append(new String(ch, start, length));
    }
    @Override
    public void endElement(String uri, String localName, String qName) {
        String text = currentText.toString().trim();
        if (qName.equals("timestamp") && inTimestamp) {
            currentTimestamp = text;
            inTimestamp = false;
        } else if (qName.equals("message") && inMessage) {
            if (isError) {
                errorLogs.add(new LogEntry(currentTimestamp, text));
            }
            inMessage = false;
        } else if (qName.equals("entry")) {
            isError = false;
        }
    }
    public List<LogEntry> getErrorLogs() {
        return errorLogs;
    }
}
public class LogAnalyzer {
    public static void main(String[] args) {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            ErrorLogHandler handler = new ErrorLogHandler();
            long startTime = System.currentTimeMillis();
            // 大きなログファイルを解析
            parser.parse(new File("large_log.xml"), handler);
            long endTime = System.currentTimeMillis();
            // 結果を表示
            List<LogEntry> errors = handler.getErrorLogs();
            System.out.println("=== エラーログ ===");
            for (LogEntry log : errors) {
                System.out.println(log);
            }
            System.out.println("\n総エラー数: " + errors.size());
            System.out.println("処理時間: " + (endTime - startTime) + "ms");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
出力例:
=== エラーログ ===
2024-01-01 10:05:00 - データベース接続エラー
2024-01-01 11:30:15 - ファイル読み込みエラー
2024-01-01 14:22:33 - メモリ不足
総エラー数: 3
処理時間: 2500ms
DOM方式では数十秒かかる処理が、SAXなら数秒で完了します。
例2:XMLを別形式に変換
シナリオ:
XMLデータをCSVに変換する
Pythonでの実装:
import xml.sax
import csv
class XMLtoCSVHandler(xml.sax.ContentHandler):
    """XMLをCSVに変換するハンドラー"""
    def __init__(self, csv_writer):
        self.csv_writer = csv_writer
        self.current_book = {}
        self.current_element = ""
        self.current_text = ""
    def startElement(self, name, attrs):
        self.current_element = name
        self.current_text = ""
        if name == "book":
            self.current_book = {"id": attrs.get("id", "")}
    def characters(self, content):
        self.current_text += content
    def endElement(self, name):
        text = self.current_text.strip()
        if name in ["title", "author", "price", "year"]:
            self.current_book[name] = text
        elif name == "book":
            # 書籍情報をCSVに書き込む
            self.csv_writer.writerow([
                self.current_book.get("id", ""),
                self.current_book.get("title", ""),
                self.current_book.get("author", ""),
                self.current_book.get("price", ""),
                self.current_book.get("year", "")
            ])
            self.current_book = {}
        self.current_text = ""
# メイン処理
if __name__ == "__main__":
    # CSVファイルを開く
    with open("books.csv", "w", newline="", encoding="utf-8") as csvfile:
        csv_writer = csv.writer(csvfile)
        # ヘッダーを書き込む
        csv_writer.writerow(["ID", "タイトル", "著者", "価格", "年"])
        # SAXパーサーを作成
        parser = xml.sax.make_parser()
        handler = XMLtoCSVHandler(csv_writer)
        parser.setContentHandler(handler)
        # XMLを解析してCSVに変換
        try:
            parser.parse("books.xml")
            print("CSVファイルの生成が完了しました")
        except Exception as e:
            print(f"エラー: {e}")
生成されるCSV:
ID,タイトル,著者,価格,年
001,プログラミング入門,山田太郎,2500,2024
002,データベース設計,佐藤花子,3200,2023
トラブルシューティング
SAXを使う際によくある問題と解決策です。
問題1:文字データが分割される
症状:characters()メソッドが複数回呼ばれ、テキストが分割される
原因:
SAXパーサーは、パフォーマンスのために文字データを分割して渡すことがあります。
解決策:
StringBuilderなどで文字を蓄積する
private StringBuilder currentText = new StringBuilder();
public void startElement(...) {
    currentText.setLength(0);  // クリア
}
public void characters(char[] ch, int start, int length) {
    currentText.append(new String(ch, start, length));  // 蓄積
}
public void endElement(...) {
    String text = currentText.toString().trim();  // 使用
}
問題2:階層構造の追跡が難しい
症状:
今どの要素の中にいるか分からなくなる
解決策:
スタックを使って階層を追跡
import java.util.Stack;
class MyHandler extends DefaultHandler {
    private Stack<String> elementStack = new Stack<>();
    public void startElement(...) {
        elementStack.push(qName);
        // 現在の階層を確認
        if (elementStack.size() >= 2 &&
            elementStack.get(elementStack.size() - 2).equals("book") &&
            qName.equals("title")) {
            // bookの直下のtitleの場合
        }
    }
    public void endElement(...) {
        elementStack.pop();
    }
}
問題3:エンコーディングの問題
症状:
日本語が文字化けする
解決策:
XML宣言でエンコーディングを指定
<?xml version="1.0" encoding="UTF-8"?>
Javaコードでも指定:
InputSource source = new InputSource(new FileInputStream("books.xml"));
source.setEncoding("UTF-8");
parser.parse(source, handler);
問題4:メモリ使用量が増える
症状:
SAXを使っているのにメモリが増え続ける
原因:
ハンドラー内で大量のデータを保持している
解決策:
必要なデータだけを保持し、不要になったらすぐに破棄
public void endElement(...) {
    // データを処理
    processData(currentData);
    // すぐに破棄
    currentData = null;
}
問題5:エラー処理が不十分
症状:
XMLの形式エラーでプログラムが停止する
解決策:
エラーハンドリングを実装
@Override
public void error(SAXParseException e) throws SAXException {
    System.err.println("エラー(行" + e.getLineNumber() + "): " + e.getMessage());
}
@Override
public void fatalError(SAXParseException e) throws SAXException {
    System.err.println("致命的エラー(行" + e.getLineNumber() + "): " + e.getMessage());
    throw e;
}
@Override
public void warning(SAXParseException e) throws SAXException {
    System.err.println("警告(行" + e.getLineNumber() + "): " + e.getMessage());
}
まとめ:SAXは大規模XML処理の強い味方
SAX(Simple API for XML)は、XML解析のための効率的なイベント駆動型APIです。
この記事のポイント:
- SAXの特徴:イベント駆動方式でXMLを順次処理
 - メリット:メモリ効率が良い、高速、大きなファイルに対応
 - デメリット:一方通行、状態管理が必要、コードが複雑
 - DOMとの違い:DOMは全体をメモリに読み込む、SAXは少しずつ処理
 - 主なイベント:startDocument、startElement、characters、endElement、endDocument
 - 適している場面:大きなXMLファイル、メモリが限られた環境、順次処理で十分な場合
 - 実装:Java、Python、C#など多くの言語で利用可能
 - 実践例:ログ解析、データ変換、情報抽出
 - 注意点:文字データの分割、階層追跡、エンコーディング
 
数MB程度の小さなXMLなら、DOMの方が簡単で使いやすいです。
しかし、数十MB〜数GBの大きなファイルや、メモリが限られた環境では、SAXが威力を発揮します。
最初はイベント駆動の概念に戸惑うかもしれませんが、慣れれば非常に強力なツールになります。特に、ビッグデータやログ解析の分野では、SAXの知識が役立つでしょう。
XMLを扱う機会があったら、ファイルのサイズや処理内容に応じて、DOMとSAXを使い分けてみてください。適切なツールを選ぶことで、効率的なプログラムが作れるようになります。
  
  
  
  
              
              
              
              
              
コメント