XML 作為結構化數據交換標準,在 API 對接、配置文件、RSS/Atom、Office 文檔、SVG 等場景廣泛應用。PHP 提供了四種主流解析方式,各有優劣。本文將系統對比 **DOM、SAX、SimpleXML、正則表達式** 的原理、效能、記憶體佔用、適用場景,並給出生產級代碼範例與避坑指南。
header('Content-Type: text/html; charset=utf-8')<meta charset="utf-8">$pdo->exec("SET NAMES utf8mb4")mb_convert_encoding($str, 'UTF-8', 'GBK') 或 iconv('GBK', 'UTF-8', $str)move_uploaded_file、filesize、readfile)不支援 UTF-8 路徑,**需轉為系統編碼(GBK/CP936)或改用無中文路徑策略**<?php
$dom = new DOMDocument();
$dom->load('books.xml'); // 或 loadXML($string)
$books = $dom->getElementsByTagName('book');
foreach ($books as $book) {
$author = $book->getElementsByTagName('author')->item(0)->nodeValue ?? '';
$title = $book->getElementsByTagName('title')->item(0)->nodeValue ?? '';
$pub = $book->getElementsByTagName('publisher')->item(0)->nodeValue ?? '';
echo "$title - $author - $pub\n";
}
// XPath 查詢(強大)
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//book[author="Jack Herrington"]/title');
foreach ($nodes as $n) echo $n->nodeValue . "\n";
// 建立 XML
$dom = new DOMDocument('1.0', 'utf-8');
$root = $dom->createElement('books');
$dom->appendChild($root);
$book = $dom->createElement('book');
$book->appendChild($dom->createElement('title', 'New Book'));
$root->appendChild($book);
echo $dom->saveXML();
?>
<?php
$reader = new XMLReader();
$reader->open('books.xml');
$books = [];
$current = null;
while ($reader->read()) {
if ($reader->nodeType === XMLReader::ELEMENT) {
if ($reader->name === 'book') {
$current = ['author' => '', 'title' => '', 'publisher' => ''];
} elseif ($current !== null && in_array($reader->name, ['author', 'title', 'publisher'])) {
$reader->read(); // 移到文本節點
$current[$reader->name] = $reader->value;
}
} elseif ($reader->nodeType === XMLReader::END_ELEMENT && $reader->name === 'book') {
$books[] = $current;
$current = null;
}
}
$reader->close();
foreach ($books as $b) {
echo "{$b['title']} - {$b['author']} - {$b['publisher']}\n";
}
?>
['attr'],子節點用 ->tag$xml->xpath('//book/title')<?php
$xml = simplexml_load_file('books.xml'); // 或 simplexml_load_string($str)
foreach ($xml->book as $book) {
// 屬性訪問
$id = (string)$book['id'];
// 子節點訪問(自動轉字符串)
$author = (string)$book->author;
$title = (string)$book->title;
$pub = (string)$book->publisher;
echo "$title - $author - $pub\n";
}
// 命名空間處理
$xml->registerXPathNamespace('ns', 'https://example.com/ns');
$items = $xml->xpath('//ns:item');
// 修改並保存
$xml->book[0]->title = 'Updated Title';
$xml->asXML('books_updated.xml');
?>
<?php
$xml = file_get_contents('books.xml');
preg_match_all('/(.*?)<\/book>/s', $xml, $blocks);
foreach ($blocks[1] as $block) {
preg_match('/(.*?)<\/author>/', $block, $a);
preg_match('/(.*?)<\/title>/', $block, $t);
preg_match('/(.*?)<\/publisher>/', $block, $p);
echo "{$t[1]} - {$a[1]} - {$p[1]}\n";
}
?>
| 維度 | DOMDocument | XMLReader/SAX | SimpleXML | 正則 |
|---|---|---|---|---|
| 記憶體佔用 | 高(全樹) | **極低(流式)** | 高(全樹) | 中(全文本) |
| 最大文件 | < 50MB | **無限制(GB+)** | < 50MB | < 10MB |
| 隨機訪問 | ✅ 完整 | ❌ 單向 | ✅ 物件圖 | ❌ |
| 修改/寫入 | ✅ 豐富 API | ❌ | ✅ 簡單修改 | ❌ |
| XPath 支援 | ✅ DOMXPath | ❌ | ✅ ->xpath() | ❌ |
| 命名空間 | ✅ 完整 | ✅ 手動處理 | ✅ registerXPathNamespace | ❌ 極難 |
| 學習曲線 | 中等 | 較高 | **極低** | 低(但極易出錯) |
| 效能(小文件) | 中 | 慢(PHP 層循環) | **最快** | 中 |
| 穩健性 | **最高** | 高 | 高 | **極低** |
文件 > 100MB 或 記憶體受限?
├─ 是 → XMLReader (流式)
└─ 否 → 需要修改/寫入/複雜 XPath?
├─ 是 → DOMDocument
└─ 否 → 純讀取、結構固定、追求開發速度?
├─ 是 → SimpleXML (首選)
└─ 否 → DOMDocument (標準、通用)
libxml_use_internal_errors(true) 捕獲解析錯誤,避免 Warning 污染日誌libxml_disable_entity_loader(true) 防止 XXE 攻擊(PHP 8.0+ 預設開啟)PHP XML 解析沒有銀彈:**SimpleXML 是 90% 場景的最佳選擇(讀取)**,**DOMDocument 處理寫入與複雜查詢**,**XMLReader 攻克大文件**,**正則僅作應急**。掌握四者優劣與避坑指南,才能在異構系統集成、API 對接、配置管理中游刃有餘。