| 擴展 | 模型 | 記憶體 | 速度 | 功能豐富度 | 適用場景 |
|---|---|---|---|---|---|
| DOMDocument | 樹狀 (DOM) | 高(整份文檔載入記憶體) | 中 | 最高(完整 CRUD、XPath、Schema 驗證、命名空間) | 需修改 XML、複雜結構、文檔較小(<10MB) |
| SimpleXML | 樹狀 (簡化 DOM) | 高(整份文檔載入) | 快(比 DOM 輕量) | 中(唯讀導向、支援 XPath、易於物件屬性存取) | 讀取小型 XML、配置檔、API 回應、無命名空間 |
| XMLReader | 流式 (Pull/Pull-based) | 極低(游標逐節點讀取) | 最快(大檔案) | 基礎(唯讀、前向、可跳過、可展開子樹) | 大型 XML(>50MB)、流式處理、記憶體受限環境 |
new DOMDocument()、loadXML()、load()、createElement()、createAttribute()getElementsByTagName()、getElementById()、XPath (DOMXPath)appendChild()、replaceChild()、removeChild()、setAttribute()saveXML() (字串)、save() (檔案)、formatOutput=true 美化縮排<?php
$xmlString = <<
login
imdonkey
XML;
$dom = new DOMDocument();
$dom->loadXML($xmlString);
$dom->formatOutput = true;
// 遞歸轉陣列
function domToArray(DOMNode $node) {
$arr = [];
// 屬性
if ($node->hasAttributes()) {
foreach ($node->attributes as $attr) {
$arr['@attributes'][$attr->nodeName] = $attr->nodeValue;
}
}
// 子節點
if ($node->hasChildNodes()) {
foreach ($node->childNodes as $child) {
if ($child->nodeType === XML_TEXT_NODE) {
$text = trim($child->nodeValue);
if ($text !== '') $arr['#text'] = $text;
} elseif ($child->nodeType === XML_ELEMENT_NODE) {
$key = $child->nodeName;
$value = domToArray($child);
if (isset($arr[$key])) {
if (!isset($arr[$key][0])) $arr[$key] = [$arr[$key]];
$arr[$key][] = $value;
} else {
$arr[$key] = $value;
}
}
}
}
return $arr ?: ($node->nodeValue ?? '');
}
print_r(domToArray($dom->documentElement));
// 輸出示例:
/*
Array
(
[cmd] => Array
(
[@attributes] => Array ( [attr] => default )
[#text] => login
)
[login] => imdonkey
)
*/
?>
<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$root = $dom->createElement('users');
$dom->appendChild($root);
$user = $dom->createElement('user');
$user->setAttribute('id', '1001');
$root->appendChild($user);
$name = $dom->createElement('name', 'John Doe');
$user->appendChild($name);
$email = $dom->createElement('email', 'john@example.com');
$user->appendChild($email);
echo $dom->saveXML();
/*
John Doe
john@example.com
*/
?>
simplexml_load_string($xmlString) — 從字串simplexml_load_file($filename) — 從檔案/URLsimplexml_import_dom($domNode) — 從 DOMNode 轉換皆回傳 SimpleXMLElement 物件,屬性存取如 $xml->login,屬性值 $xml->cmd['attr']。
<?php
$xml = simplexml_load_string($xmlString);
echo $xml->cmd . "\n"; // login (SimpleXMLElement 物件)
echo (string)$xml->cmd . "\n"; // login (強制轉字串)
echo $xml->cmd['attr'] . "\n"; // default (屬性)
echo $xml->login . "\n"; // imdonkey
// 迴圈子元素
foreach ($xml->children() as $child) {
echo $child->getName() . ': ' . $child . "\n";
}
// XPath 查詢
$results = $xml->xpath('//cmd[@attr="default"]');
print_r($results);
?>
registerXPathNamespace)。open($uri, $encoding='UTF-8') / xml($source, $encoding)read() — 移動到下一節點,返回 true/falsename、nodeType、getAttribute($name)、readOuterXml()、expand() (轉 DOMNode)close()XMLReader::ELEMENT (1) — 開始標籤XMLReader::TEXT (3) — 文字內容XMLReader::END_ELEMENT (15) — 結束標籤<?php
$uri = 'https://www.google.com/ig/api?weather=Beijing&hl=zh-cn';
$reader = new XMLReader();
$reader->open($uri, 'GBK'); // API 返回 GBK
$current = $forecast = [];
while ($reader->read()) {
// 當前天氣區塊
if ($reader->name === 'current_conditions' && $reader->nodeType === XMLReader::ELEMENT) {
while ($reader->read() && $reader->name !== 'current_conditions') {
if ($reader->nodeType === XMLReader::ELEMENT) {
$current[$reader->name] = $reader->getAttribute('data');
}
}
}
// 預報區塊(多個)
if ($reader->name === 'forecast_conditions' && $reader->nodeType === XMLReader::ELEMENT) {
$day = [];
while ($reader->read() && $reader->name !== 'forecast_conditions') {
if ($reader->nodeType === XMLReader::ELEMENT) {
$day[$reader->name] = $reader->getAttribute('data');
}
}
$forecast[] = $day;
}
}
$reader->close();
print_r($current);
print_r($forecast);
/*
Array
(
[temp_c] => 22
[condition] => 多雲
[humidity] => 濕度: 60%
[wind_condition] => 風: 東北風 10 km/h
)
Array
(
[0] => Array ( [day_of_week] => 週一, [low] => 15, [high] => 25, [condition] => 晴 )
[1] => Array ( [day_of_week] => 週二, [low] => 14, [high] => 24, [condition] => 陰 )
)
*/
?>
xml_parser_create() (較底層,不推薦新專案)iconv() 或 mb_convert_encoding() 轉碼再載入。open() 指定編碼(如 'GBK'、'BIG5'),內部自動轉 UTF-8。header('Content-Type: application/xml; charset=UTF-8')。