為什麼不建議用 Regex 處理 XML?
- XML 結構巢狀、屬性、命名空間、CDATA、轉義字元複雜,Regex 極難完整涵蓋。
- PHP 內建 SimpleXML、DOMDocument、XMLReader 等專用擴展,效能好、容錯率高。
範例 XML (data.xml)
23
開心的路飛
男
face/43.jpg
123@qq.com
1212121212
讀取 XML - SimpleXML (最簡潔)
id}\n";
echo "姓名: {$xml->username}\n";
echo "性別: {$xml->sex}\n";
echo "大頭照: {$xml->face}\n";
echo "Email: {$xml->email}\n";
echo "QQ: {$xml->qq}\n";
// 轉陣列
$arr = json_decode(json_encode($xml), true);
print_r($arr);
寫入 XML - DOMDocument (標準、支援格式化)
formatOutput = true; // 美化縮排
$dom->preserveWhiteSpace = false;
$root = $dom->createElement('vip');
$dom->appendChild($root);
foreach ($data as $key => $value) {
$el = $dom->createElement($key);
$el->appendChild($dom->createTextNode($value));
$root->appendChild($el);
}
// 原子寫入:先寫暫存檔再 rename,避免並發損壞
$tmp = $file . '.tmp';
if ($dom->save($tmp)) {
return rename($tmp, $file);
}
return false;
}
// 使用範例
$newData = [
'id' => 24,
'username' => '新用戶',
'sex' => '女',
'face' => 'face/99.jpg',
'email' => 'new@example.com',
'qq' => '987654321'
];
writeVipXml('newuser.xml', $newData);
進階:XMLReader 大檔案串流讀取 (低記憶體)
open('large.xml');
while ($reader->read()) {
if ($reader->nodeType === XMLReader::ELEMENT && $reader->localName === 'vip') {
$node = simplexml_import_dom($reader->expand());
// 處理單筆 $node
echo "處理 ID: {$node->id}\n";
}
}
$reader->close();
常見陷阱與最佳實務
| 問題 | 解決 |
| 中文亂碼 | 確保 XML 宣告 encoding="utf-8",PHP 檔案亦為 UTF-8 無 BOM |
| 實體字元未轉義 | 用 createTextNode 或 htmlspecialchars,不要直接拼字串 |
| 大檔案記憶體爆炸 | 改用 XMLReader 串流處理 |
| 命名空間 | SimpleXML 用 ->children('ns', true),DOM 用 createElementNS |
| 並發寫入損壞 | 寫暫存檔 + rename() 原子替換,或加檔案鎖 flock() |