首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 將 XML 轉換為陣列:SimpleXML + JSON 中轉法與陷阱避坑

     編輯:PHP 綜合知識

核心技巧:SimpleXML → JSON → Array

json_encode() 可直接序列化 SimpleXMLElement,再 json_decode(..., true) 得到純陣列。此法簡潔、無需遞歸遍歷。

代碼實現

function xmlToArray($xmlString) {
    // 1. 載入 XML (支援字串或檔案)
    $xml = simplexml_load_string($xmlString);
    // $xml = simplexml_load_file('data.xml'); // 從檔案

    if ($xml === false) {
        throw new Exception('XML 解析失敗');
    }

    // 2. 轉 JSON (SimpleXMLElement 實現 JsonSerializable)
    $json = json_encode($xml, JSON_UNESCAPED_UNICODE);
    if ($json === false) {
        throw new Exception('JSON 編碼失敗: ' . json_last_error_msg());
    }

    // 3. 解碼為關聯陣列
    $array = json_decode($json, true);
    return $array;
}

// 測試
$xmlStr = <<

    Forty What?
    Joe
    Jane
    I know that's the answer -- but what's the question?

XML;

$arr = xmlToArray($xmlStr);
print_r($arr);

輸出結果

Array
(
    [title] => Forty What?
    [from] => Joe
    [to] => Jane
    [body] => I know that's the answer -- but what's the question?
)

常見陷阱與解決

1. 同名子節點變為索引陣列

$xml = simplexml_load_string('12');
$arr = json_decode(json_encode($xml), true);
// 結果:['item' => ['1', '2']]  (正確)

但若只有一個 <item>,結果為 ['item' => '1'] (字串而非陣列)。

修正:預先在 XML 加入屬性 multiple="true" 或後處理強制轉陣列。

2. 屬性丟失

$xml = simplexml_load_string('text');
$arr = json_decode(json_encode($xml), true);
// 結果:['node' => 'text']  (屬性 @attributes 丟失)

解決:使用 simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA) 並手動合併 ->attributes(),或改用 DOMDocument 完整解析。

3. 命名空間

SimpleXML 命名空間處理繁瑣,建議改用 DOMDocument + XPath。

4. 大文件記憶體

simplexml_load_string 需將整個 XML 載入記憶體。超大文件請用 XMLReader (拉式解析) 逐節點處理。

進階:健壯的通用轉換函數

function xmlToArrayRobust($xml, $options = 0) {
    if (is_string($xml)) {
        $xml = simplexml_load_string($xml, 'SimpleXMLElement', $options | LIBXML_NOCDATA);
    } elseif ($xml instanceof SimpleXMLElement) {
        // already object
    } else {
        throw new InvalidArgumentException('Invalid XML input');
    }

    $json = json_encode($xml, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $arr = json_decode($json, true);

    // 修正單一子節點非陣列問題
    array_walk_recursive($arr, function(&$v, $k) {
        // 可在此統一類型轉換
    });

    return $arr;
}

替代方案:DOMDocument + XPath (保留屬性、命名空間、CDATA)

function domToArray($xmlString) {
    $dom = new DOMDocument();
    $dom->loadXML($xmlString);
    $xpath = new DOMXPath($dom);

    $result = [];
    foreach ($xpath->query('/*/*') as $node) {
        $result[$node->nodeName] = $node->nodeValue; // 簡化版,實際需遞歸處理屬性/子節點
    }
    return $result;
}

總結選型

場景推薦方案
簡單 XML、無屬性/命名空間、中小文件SimpleXML + JSON 中轉 (最簡潔)
需保留屬性、CDATA、命名空間DOMDocument + 遞歸遍歷
超大文件 (百 MB+)XMLReader (流式解析)
高效能、頻繁轉換編譯期生成 PHP 類 (如 goetas/xsd-to-php)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved