PHP 5 引入 SimpleXML 解決了傳統 XML 處理的兩極痛點:
SimpleXML 以物件屬性存取 + 迭代器遍歷 + XPath 查詢 三位一體,讓 XML 操作像處理 JSON 一樣自然,且支援大文件流式讀取(simplexml_load_file 底層用 libxml2 流式解析)。
| 任務 | 方法/語法 | 備註 |
|---|---|---|
| 從檔案載入 | simplexml_load_file('file.xml') | 回傳 SimpleXMLElement 根節點 |
| 從字串載入 | simplexml_load_string($xmlStr) | |
| 從 DOM 轉換 | simplexml_import_dom($domNode) | 互通性佳 |
| 直接建構 | new SimpleXMLElement('<root/>') | 最常用 |
| 存取子節點 | $xml->node / $xml->node[0] | 同名節點自動成陣列 |
| 存取屬性 | $xml['attr'] / $xml->node['attr'] | 關聯陣列語法 |
| XPath 查詢 | $xml->xpath('//path') | 回傳節點陣列 |
| 遍歷子節點 | foreach($xml->children() as $c) | |
| 修改內容 | $xml->node = 'new' | 直接賦值 |
| 新增節點 | $xml->addChild('name', 'val') | 或 $xml->node[] = '' 先佔位 |
| 新增屬性 | $xml->node['attr'] = 'val' | |
| 輸出 XML | $xml->asXML('file.xml') | 或 echo $xml->asXML() |
<?xml version="1.0"?>
<Messages>
<msg id="1">
<title>This is Title</title>
<content>Here is Content</content>
<time>2008-03-20 21:50:23</time>
<reply id="11">reply 1</reply>
<reply id="12">reply 2</reply>
</msg>
</Messages>
$xml = simplexml_load_file('Messages.xml');
// 1. 直接屬性存取
echo $xml->msg->title; // This is Title
// 2. 同名節點索引
echo $xml->msg->reply[0]; // reply 1
// 3. 屬性存取
echo $xml->msg['id']; // 1
echo $xml->msg->reply[1]['id']; // 12
// 4. 遍歷
foreach ($xml->msg->reply as $reply) {
echo $reply['id']; // 11, 12
}
// 5. XPath 深度搜尋
foreach ($xml->xpath('//reply') as $reply) {
echo $reply . '<br>';
}
// 6. 遍歷所有子節點
foreach ($xml->msg->children() as $field) {
echo $field . '<br>';
}
msg->time = '2008-03-21 00:53:12';
// 8. 修改屬性
$xml->msg->reply[1]['id'] = '222';
// 9. 新增子節點(簡單賦值)
$xml->msg->author = 'zhangsan';
// 10. 新增屬性
$xml->msg['author'] = 'zhangsan';
// 11. 儲存
$xml->asXML('MessagesNew.xml');
// 錯誤:直接對不存在的 $xml->message[0] 賦值會報 Fatal Error
$xml->message[0]['id'] = 1; // Objects used as arrays... must return values by reference
// 正確:先建立空節點佔位
$xml->message[0] = ''; // 關鍵步驟!
$xml->message[0]['id'] = 1;
$xml->message[0]->title = 'New Title';
<?php
$xml = new SimpleXMLElement('<Messages/>');
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', 'root');
$stmt = $pdo->query('SELECT * FROM messages');
$i = 0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$xml->message[$i] = ''; // 佔位
$xml->message[$i]['id'] = $row['id'];
$xml->message[$i]->title = $row['title'];
$xml->message[$i]->content = $row['content'];
$xml->message[$i]->time = $row['time'];
$replies = $pdo->query("SELECT * FROM replies WHERE mid={$row['id']}");
$j = 0;
while ($r = $replies->fetch(PDO::FETCH_ASSOC)) {
$xml->message[$i]->reply[$j] = $r['reply'];
$xml->message[$i]->reply[$j]['id'] = $r['id'];
$j++;
}
$i++;
}
$xml->asXML('messages.xml');
?>
<?php
$xml = simplexml_load_file('messages.xml');
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', 'root');
$pdo->beginTransaction();
foreach ($xml->message as $msg) {
$stmt = $pdo->prepare('INSERT INTO messages (id, title, content, time) VALUES (?,?,?,?)');
$stmt->execute([$msg['id'], $msg->title, $msg->content, $msg->time]);
$mid = (int)$msg['id'];
foreach ($msg->reply as $reply) {
$stmt = $pdo->prepare('INSERT INTO replies (mid, id, reply) VALUES (?,?,?)');
$stmt->execute([$mid, $reply['id'], (string)$reply]);
}
}
$pdo->commit();
?>
simplexml_load_file 最簡便XMLReader (pull parser) 流式讀取,避免全量載入記憶體asXML 或改用 XMLWriter 流式輸出$xml->registerXPathNamespace('ns', 'https://example.com/ns');
$items = $xml->xpath('//ns:item');
SimpleXML 以極簡 API 覆蓋 90% XML 處理需求,是 PHP 開發者處理配置檔、API 回應、資料交換的首選工具。掌握「佔位再賦值」與「XPath 深度查詢」兩大核心技巧,即可輕鬆應對複雜結構轉換。大文件場景請無縫切換至 XMLReader/Writer,同屬 libxml2 家族,學習成本極低。