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

PHP 解析 XML 完整指南:DOMDocument、SimpleXML、XMLReader 三大擴展深度比較與實戰代碼

     編輯:PHP 相關知識

    PHP 三大 XML 擴展對比

    擴展模型記憶體速度功能豐富度適用場景
    DOMDocument樹狀 (DOM)高(整份文檔載入記憶體)中最高(完整 CRUD、XPath、Schema 驗證、命名空間)需修改 XML、複雜結構、文檔較小(<10MB)
    SimpleXML樹狀 (簡化 DOM)高(整份文檔載入)快(比 DOM 輕量)中(唯讀導向、支援 XPath、易於物件屬性存取)讀取小型 XML、配置檔、API 回應、無命名空間
    XMLReader流式 (Pull/Pull-based)極低(游標逐節點讀取)最快(大檔案)基礎(唯讀、前向、可跳過、可展開子樹)大型 XML(>50MB)、流式處理、記憶體受限環境

    1. DOMDocument — 完整控制、支援寫入

    核心 API 速查

    • 建立: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
    )
    */
    ?>

    建立 XML 範例

    <?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
      
    
    */
    ?>

    2. SimpleXML — 簡潔易用、適合唯讀

    三大入口函數

    • simplexml_load_string($xmlString) — 從字串
    • simplexml_load_file($filename) — 從檔案/URL
    • simplexml_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)。
    • 大檔案會耗盡記憶體。
    • 寫入/修改較繁瑣(需轉 DOM 或重新組裝字串)。

    3. XMLReader — 流式處理大檔案王者

    核心方法

    • open($uri, $encoding='UTF-8') / xml($source, $encoding)
    • read() — 移動到下一節點,返回 true/false
    • name、nodeType、getAttribute($name)、readOuterXml()、expand() (轉 DOMNode)
    • close()

    節點類型常數

    • XMLReader::ELEMENT (1) — 開始標籤
    • XMLReader::TEXT (3) — 文字內容
    • XMLReader::END_ELEMENT (15) — 結束標籤

    實戰:解析 Google 天氣 API (大型 XML 流)

    <?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] => 陰 )
    )
    */
    ?>

    選型決策樹

    1. 檔案 < 5MB 且需修改/寫入 → DOMDocument
    2. 檔案 < 5MB 純讀取、結構簡單 → SimpleXML
    3. 檔案 > 50MB 或記憶體受限 → XMLReader
    4. 需 XPath/Schema 驗證/命名空間 → DOMDocument + DOMXPath
    5. SAX 事件驅動習慣 → xml_parser_create() (較底層,不推薦新專案)

    編碼注意事項

    • DOMDocument/SimpleXML 僅支援 UTF-8。非 UTF-8 檔案需先 iconv() 或 mb_convert_encoding() 轉碼再載入。
    • XMLReader 可在 open() 指定編碼(如 'GBK'、'BIG5'),內部自動轉 UTF-8。
    • 輸出時設定 header('Content-Type: application/xml; charset=UTF-8')。
    1. 上一篇文章:
    2. 下一篇文章:
    Copyright © 程式碼之家 All Rights Reserved