PHP 的 DOMDocument 提供標準、健壯的 XML 解析能力,適合處理結構固定、需求精確對應的設定檔或資料交換。本文示範如何將巢狀 XML 轉換為二維關聯陣列。
<?xml version="1.0" encoding="utf-8"?>
<config>
<db>
<server>localhost1</server>
<root>root</root>
<pw>123</pw>
</db>
<smarty></smarty>
</config>
<?php
$doc = new DOMDocument('1.0', 'utf-8');
// 抑制格式不完美 XML 的警告 (可選)
libxml_use_internal_errors(true);
$doc->load('config.xml');
libxml_clear_errors();
$root = $doc->documentElement; // 取得根節點
$configs = [];
// 遍歷根節點直屬子節點 (, )
foreach ($root->childNodes as $child) {
// 過濾文字節點 (換行、縮排空白)
if ($child->nodeType !== XML_ELEMENT_NODE) continue;
$sectionName = $child->nodeName; // 'db' 或 'smarty'
$configs[$sectionName] = [];
// 遍歷二層子節點 (, , )
foreach ($child->childNodes as $item) {
if ($item->nodeType !== XML_ELEMENT_NODE) continue;
$key = $item->nodeName;
$value = $item->nodeValue; // 文字內容
$configs[$sectionName][$key] = $value;
}
}
var_dump($configs);
array(2) {
'db' => array(3) {
'server' => string(10) "localhost1"
'root' => string(4) "root"
'pw' => string(3) "123"
}
'smarty' => array(0) {
}
}
| 屬性/方法 | 說明 |
|---|---|
documentElement | 直接取得根元素節點,略過 XML 宣告、DOCTYPE 等 |
childNodes | 回傳 DOMNodeList,包含**所有**節點類型 (元素、文字、註解、CDATA) |
nodeType === XML_ELEMENT_NODE | **必要過濾**:略過換行縮排產生的文字節點 (#text) |
nodeName | 元素標籤名 (如 db, server) |
nodeValue | 元素內的文字內容 (遞迴包含子孫文字) |
libxml_use_internal_errors(true) | 避免 load() 遇到不嚴格 XML 時噴出 E_WARNING |
function domNodeToArray(DOMNode $node): array {
$result = [];
foreach ($node->childNodes as $child) {
if ($child->nodeType !== XML_ELEMENT_NODE) continue;
if ($child->childNodes->length === 1 && $child->firstChild->nodeType === XML_TEXT_NODE) {
// 葉子節點:直接取值
$result[$child->nodeName] = $child->nodeValue;
} else {
// 分支節點:遞迴
$result[$child->nodeName] = domNodeToArray($child);
}
}
return $result;
}
// 使用
$configs = domNodeToArray($doc->documentElement);
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
simplexml_load_file() | 語法極簡、自動轉物件/陣列 | 大檔案記憶體佔用高、命名空間處理麻煩 | 小型、結構簡單 XML |
DOMDocument | 標準 DOM API、記憶體效率好 (可流式)、支援 XPath、Schema 驗證 | 程式碼較冗長 | 企業級、大檔案、需精確控制 |
XMLReader | 拉式解析、極低記憶體、速度最快 | 單向游標、邏輯較複雜 | 超大 XML (GB 級)、串流處理 |
load() 失敗,讀取前可 $content = preg_replace('/^\xEF\xBB\xBF/', '', file_get_contents($file))。encoding="gb2312" 但實際為 UTF-8,需手動 $doc->encoding = 'utf-8' 或 iconv 轉碼。$result[$name][] = $value 收集陣列。nodeValue 會正確回傳 CDATA 內容,無需特殊處理。DOMDocument 配合 nodeType 過濾,能穩健地將 XML 結構映射為 PHP 陣列。掌握「元素節點遞迴 + 文字節點取值」模式,即可應對各類 XML 解析需求。