PHP 提供四種主流 XML 解析方式,各有擅長場景。本文從原理、記憶體模型、API 風格、效能、適用場景五個維度深度對比,助你精準選型。
| 解析器 | 模型 | 記憶體 | API 風格 | 支援編碼 | 命名空間 | 適用場景 |
|---|---|---|---|---|---|---|
| XML Expat Parser | SAX(事件推送) | 流式,極低 | 回調函數 | UTF-8/ISO-8859-1/US-ASCII | 弱 | 大檔、高效能、單向讀取 |
| SimpleXML | 樹狀(DOM-like) | 全載入 | 物件屬性存取 | UTF-8 | 弱 | 小檔、結構固定、快速開發 |
| XMLReader | Pull(游標拉取) | 流式,極低 | 迭代器 | libxml 全支援 | 強 | 大檔、需跳過節點、雙向控制 |
| DOMDocument | 樹狀(W3C DOM) | 全載入 | DOM API | UTF-8 | 強 | 需修改/寫入 XML、複雜查詢 |
PHP 4 就有,底層用 Expat C 庫。邊讀邊解析,不載入整份文件。
xml_parse_into_struct():一次解析成兩個陣列(索引/值),適合結構固定的小中型 XML。xml_set_element_handler() + xml_set_character_data_handler():設定開始/結束標籤、文字資料回調,邏輯清晰、適合複雜結構。<?php // 回調模式範例 $parser = xml_parser_create(); xml_set_element_handler($parser, 'startTag', 'endTag'); xml_set_character_data_handler($parser, 'cdata'); xml_parse($parser, $xmlString); xml_parser_free($parser); ?>
⚠️ 只支援三種編碼,非 UTF-8 需先 iconv/mb_convert_encoding 轉換。
將 XML 轉為 SimpleXMLElement 物件,屬性/子節點直接用 -> 存取。
<?php $xml = simplexml_load_string($str); echo $xml->cmd; // 直接取值 echo (string)$xml->login; // 強制轉字串比較 // 修改 $xml->cmd = 'logout'; echo $xml->asXML(); ?>
✅ 開發極快、語法直覺。❌ 全載入記憶體、不支援命名空間、不容錯(格式錯誤直接報錯)。
像資料庫游標,read() 逐節點前進,隨時可 next() 跳過子樹。可控性最強,適合大檔、異構結構。
<?php
$reader = new XMLReader();
$reader->open('big.xml', 'UTF-8');
while ($reader->read()) {
if ($reader->name === 'item' && $reader->nodeType === XMLReader::ELEMENT) {
$node = $reader->expand(); // 轉 DOMNode 方便處理
// 或用 simplexml_import_dom($node) 轉 SimpleXML
}
}
$reader->close();
?>
基於 libxml,支援所有 libxml 編碼、命名空間、XPath(配合 expand())。
功能最完整:讀、寫、修改、XPath、Schema 驗證、XSLT 轉換。但全載入記憶體,大檔慎用。
<?php
$dom = new DOMDocument();
$dom->loadXML($xmlStr);
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//book[@id="3"]/title');
$nodes[0]->nodeValue = 'New Title';
echo $dom->saveXML();
?>
SimpleXML 載入快但記憶體高;流式解析器記憶體穩定但 CPU 稍高。
沒有銀彈,只有適合場景的工具。現代專案建議:預設 SimpleXML,大檔改 XMLReader,需寫入改 DOMDocument。