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

PHP 讀寫 XML 完整指南:DOM、SimpleXML、XMLReader 與效能比較

     編輯:PHP 相關知識

XML 是資料交換常用格式,PHP 提供多種解析與生成方式。本文詳細比較 DOM、SimpleXML、XMLReader、XMLWriter 的適用場景、記憶體特性與程式碼範例,協助選擇最適合的工具。

XML 基礎結構範例

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
    <book id="bk101" category="programming">
        <title>PHP 8 實戰開發</title>
        <author>王小明</author>
        <publisher>技術出版社</publisher>
        <price currency="TWD">680</price>
        <publish_date>2023-05-15</publish_date>
        <description>涵蓋 PHP 8 新特性、效能優化與最佳實踐</description>
    </book>
    <book id="bk102" category="database">
        <title>MySQL 8 管理指南</title>
        <author>李大華</author>
        <publisher>資料庫雜誌社</publisher>
        <price currency="TWD">720</price>
        <publish_date>2023-03-20</publish_date>
        <description>從安裝調校到高可用架構</description>
    </book>
</catalog>

1. DOMDocument:完整樹狀結構操作

特性:載入整份文件到記憶體、支援 XPath、可隨意修改結構、適合中小型 XML(< 50MB)

讀取與查詢

<?php
$dom = new DOMDocument();
$dom->load('books.xml');

$xpath = new DOMXPath($dom);

// 查詢所有 programming 類別的書
$books = $xpath->query('//book[@category="programming"]');
foreach ($books as $book) {
    $title = $xpath->evaluate('string(title)', $book);
    $price = $xpath->evaluate('string(price)', $book);
    $currency = $xpath->evaluate('string(price/@currency)', $book);
    echo "{$title} - {$price} {$currency}\n";
}

// 取得特定 ID 的書
$book = $dom->getElementById('bk101'); // 需先設定 ID 屬性
if (!$book) {
    $book = $xpath->query('//book[@id="bk101"]')->item(0);
}
?>

建立與修改 XML

<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true; // 美化輸出

$catalog = $dom->createElement('catalog');
$dom->appendChild($catalog);

$book = $dom->createElement('book');
$book->setAttribute('id', 'bk103');
$book->setAttribute('category', 'web');
$catalog->appendChild($book);

$title = $dom->createElement('title', 'Laravel 實戰');
$book->appendChild($title);

$author = $dom->createElement('author', '陳開發');
$book->appendChild($author);

$price = $dom->createElement('price', '850');
$price->setAttribute('currency', 'TWD');
$book->appendChild($price);

// 儲存
$dom->save('new_book.xml');
// 或輸出字串
$xmlString = $dom->saveXML();
?>

2. SimpleXML:簡易物件導向存取

特性:語法直覺、自動轉換為物件/陣列、唯讀導向、不支援複雜修改、記憶體佔用略低於 DOM

讀取範例

<?php
$xml = simplexml_load_file('books.xml');

// 存取屬性
foreach ($xml->book as $book) {
    echo "ID: {$book['id']}\n";
    echo "分類: {$book['category']}\n";
    echo "標題: {$book->title}\n";
    echo "價格: {$book->price} {$book->price['currency']}\n";
    
    // XPath 查詢
    $programmingBooks = $xml->xpath('//book[@category="programming"]');
}

// 轉陣列(含屬性)
function simpleXmlToArray(SimpleXMLElement $xml): array {
    $json = json_encode($xml);
    return json_decode($json, true);
}

$array = simpleXmlToArray($xml);
?>

建立 XML

<?php
$xml = new SimpleXMLElement('<catalog/>');

$book = $xml->addChild('book');
$book->addAttribute('id', 'bk103');
$book->addAttribute('category', 'web');
$book->addChild('title', 'Laravel 實戰');
$book->addChild('author', '陳開發');
$price = $book->addChild('price', '850');
$price->addAttribute('currency', 'TWD');

$xml->asXML('simple_book.xml');
?>

3. XMLReader:流式解析(低記憶體)

特性:游標式前向讀取、不載入整份文件、適合大型 XML(GB 級)、唯讀、速度快

<?php
$reader = new XMLReader();
$reader->open('large_catalog.xml');

$books = [];
$currentBook = null;

while ($reader->read()) {
    if ($reader->nodeType === XMLReader::ELEMENT) {
        if ($reader->name === 'book') {
            $currentBook = [
                'id' => $reader->getAttribute('id'),
                'category' => $reader->getAttribute('category'),
                'title' => '',
                'author' => '',
                'price' => '',
                'currency' => ''
            ];
        } elseif ($currentBook && in_array($reader->name, ['title', 'author', 'price'])) {
            $reader->read(); // 移到文字節點
            $currentBook[$reader->name] = $reader->value;
            if ($reader->name === 'price') {
                $currentBook['currency'] = $reader->getAttribute('currency');
            }
        }
    } elseif ($reader->nodeType === XMLReader::END_ELEMENT && $reader->name === 'book') {
        $books[] = $currentBook;
        $currentBook = null;
    }
}

$reader->close();
// $books 現在包含所有書的資料,記憶體只佔用陣列大小
?>

4. XMLWriter:流式生成 XML

特性:記憶體效率高、適合產生大型 XML 檔案、只寫不讀

<?php
$writer = new XMLWriter();
$writer->openMemory();
$writer->setIndent(true);
$writer->setIndentString('    ');
$writer->startDocument('1.0', 'UTF-8');

$writer->startElement('catalog');

for ($i = 1; $i <= 10000; $i++) {
    $writer->startElement('book');
    $writer->writeAttribute('id', "bk{$i}");
    $writer->writeAttribute('category', 'generated');
    
    $writer->writeElement('title', "Generated Book {$i}");
    $writer->writeElement('author', "Author {$i}");
    $writer->writeElement('price', rand(100, 1000));
    
    $writer->endElement(); // book
    
    // 定期輸出避免記憶體累積
    if ($i % 1000 === 0) {
        file_put_contents('generated_books.xml', $writer->outputMemory(true), FILE_APPEND);
    }
}

$writer->endElement(); // catalog
$writer->endDocument();

file_put_contents('generated_books.xml', $writer->outputMemory(true), FILE_APPEND);
?>

5. 效能與記憶體比較

解析器記憶體模式適合大小讀取速度寫入支援XPath
DOMDocument樹狀結構全載入< 50MB中完整完整支援
SimpleXML樹狀結構全載入< 30MB快基本支援
XMLReader流式(常數記憶體)無上限最快無無
XMLWriter流式(常數記憶體)無上限最快完整無

選擇指南

  • 小型配置檔、需修改結構:DOMDocument
  • 讀取已知結構資料、簡單轉陣列:SimpleXML
  • 大型 XML 匯入、資料遷移、串流處理:XMLReader
  • 產生大型 XML 匯出、報表、Sitemap:XMLWriter
  • 需複雜 XPath 查詢、XSLT 轉換:DOMDocument

命名空間處理

<?php
$xml = simplexml_load_file('namespaced.xml');
// 註冊命名空間
$xml->registerXPathNamespace('ns', 'https://example.com/ns');
$items = $xml->xpath('//ns:item');

// DOMDocument
$dom = new DOMDocument();
$dom->load('namespaced.xml');
$xpath = new DOMXPath($dom);
$xpath->registerNamespace('ns', 'https://example.com/ns');
$items = $xpath->query('//ns:item');
?>

錯誤處理與安全

<?php
// 停用外部實體載入(防止 XXE 攻擊)
libxml_disable_entity_loader(true);

// 載入時忽略警告
$dom = new DOMDocument();
$dom->loadXML($xmlString, LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NONET);

// 檢查錯誤
if ($dom->schemaValidate('schema.xsd')) {
    echo "驗證通過";
} else {
    foreach (libxml_get_errors() as $error) {
        error_log("XML 驗證錯誤:{$error->message} at line {$error->line}");
    }
    libxml_clear_errors();
}
?>

掌握這四種工具的特性與適用場景,能讓 PHP 處理 XML 任務事半功倍。現代專案建議:配置檔用 SimpleXML,資料匯入用 XMLReader,報表匯出用 XMLWriter,複雜操作用 DOMDocument。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved