XML 作為資料交換與儲存的標準格式,配合 PHP 強大的解析支援,廣泛應用於 API 串接、設定檔管理、內容發佈等場景。本文系統整理 XML 核心技術棧、PHP 解析器選擇指南、SAX/DOM 兩大解析模式差異,並提供完整通訊錄解析實戰範例。
| 技術 | 角色 | 關鍵特性 |
|---|---|---|
| DTD | 文件型別定義 | 定義元素結構、屬性類型;非 XML 撰寫,擴充性弱 |
| XML Schema (XSD) | 結構驗證 | XML 寫成、支援資料型別 (int/date/boolean)、命名空間、多 Schema 組合 |
| XPath | 節點定位語言 | 路徑表達式選取節點集,如 //book[@id='1']/title |
| XSLT | 轉換語言 | XML → HTML/文字/其他 XML,模板驅動、圖靈完備 |
| DOM | 文件物件模型 | 樹狀記憶體結構、隨機存取、雙向操作、支援命名空間 |
| SAX | 事件驅動解析 | 串流單向讀取、低記憶體、高速、無法隨機存取 |
| Namespaces | 命名空間 | URI 區分同名元素,避免合併文件衝突 |
| 擴充套件 | 模式 | 適用場景 | 記憶體 | 學習曲線 |
|---|---|---|---|---|
| XMLReader | Pull (SAX-like) | 大型檔案、單向讀取、記憶體敏感 | 極低 | 中 |
| SimpleXML | DOM (簡化) | 中小型 XML、直覺式物件存取、XPath 查詢 | 中 | 低 |
| DOMDocument | DOM (標準) | 需修改/建立 XML、複雜結構、命名空間嚴格 | 高 | 中高 |
| XML Parser (expat) | Push (SAX) | 舊專案相容、極大檔案、自訂事件處理 | 極低 | 高 |
<?xml version="1.0" encoding="UTF-8"?>
<addressbook>
<contact id="1">
<name>張三</name>
<email>zhang@example.com</email>
<phone type="mobile">0912-345678</phone>
<phone type="home">02-23456789</phone>
<address>台北市信義區忠孝東路五段 123 號</address>
</contact>
<contact id="2">
<name>李四</name>
<email>li@example.com</email>
<phone type="mobile">0923-456789</phone>
<address>新北市板橋區文化路 456 號</address>
</contact>
</addressbook>
<?php
$xml = simplexml_load_file('address.xml');
if ($xml === false) {
die("XML 解析失敗");
}
// 1. 遍歷所有聯絡人
foreach ($xml->contact as $contact) {
echo "ID: {$contact['id']}
";
echo "姓名: {$contact->name}
";
echo "Email: {$contact->email}
";
// 2. 处理多个 phone 元素
foreach ($contact->phone as $phone) {
echo "電話 ({$phone['type']}): {$phone}
";
}
echo "地址: {$contact->address}
";
}
// 3. XPath 精準查詢:找出所有行動電話
$mobiles = $xml->xpath('//phone[@type="mobile"]');
foreach ($mobiles as $mobile) {
echo "行動: {$mobile}
";
}
?>
<?php
$dom = new DOMDocument();
$dom->load('address.xml');
// 新增聯絡人
$newContact = $dom->createElement('contact');
$newContact->setAttribute('id', '3');
$name = $dom->createElement('name', '王五');
$email = $dom->createElement('email', 'wang@example.com');
$phone = $dom->createElement('phone', '0934-567890');
$phone->setAttribute('type', 'mobile');
$newContact->appendChild($name);
$newContact->appendChild($email);
$newContact->appendChild($phone);
$dom->documentElement->appendChild($newContact);
$dom->formatOutput = true; // 美化縮排
$dom->save('address.xml'); // 寫回檔案
echo "新增完成,XML 已更新";
?>
<?php
$reader = new XMLReader();
$reader->open('huge_addressbook.xml');
while ($reader->read()) {
// 只處理 contact 開始標籤
if ($reader->nodeType === XMLReader::ELEMENT && $reader->localName === 'contact') {
// 將當前節點展開為 SimpleXML 物件 (僅此節點樹)
$contactXml = $reader->expand();
$contact = simplexml_import_dom($contactXml);
echo "ID: {$contact['id']} - {$contact->name}
";
// 釋放記憶體 (重要!)
$contactXml->parentNode->removeChild($contactXml);
}
}
$reader->close();
?>
遇到帶命名空間的 XML (如 `
$xml->registerXPathNamespace('ns', 'https://example.com/ns'); $xml->xpath('//ns:book')$xpath = new DOMXPath($dom); $xpath->registerNamespace('ns', '...'); $xpath->query('//ns:book')$reader->namespaceURI 取得當前節點命名空間 URI`,PHP 檔案存為 UTF-8 無 BOM,資料庫連線 `SET NAMES utf8mb4`。preg_replace('/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/', '', $xmlString)。解析外部 XML 時,預設可能啟用外部實體 (XXE),導致檔案讀取、SSRF 等風險。必須停用:
// SimpleXML / DOMDocument
libxml_disable_entity_loader(true); // PHP 8.0+ 已預設停用,但建議顯式呼叫
// XMLReader
$reader->setParserProperty(XMLReader::VALIDATE, false);
$reader->setParserProperty(XMLReader::SUBST_ENTITIES, false);
PHP 提供豐富的 XML 處理工具鏈:SimpleXML 適合快速開發讀取、DOMDocument 適合建構/修改、XMLReader 適合大檔案串流。掌握 XPath 查詢、命名空間處理與 XXE 防護,即可安全高效地在專案中整合 XML 資料流。