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

PHP 遍歷 XML 文件所有節點:DOMDocument 現代化實作

     編輯:PHP 相關知識

早期範例使用已移除的 domxml 擴充套件(xmldocfile、walk_tree)。現代 PHP(5.0+)內建 DOMDocument 與 DOMXPath,提供標準、強大的 XML 操作 API。本文示範如何遞歸遍歷所有節點、屬性、文字內容,並處理命名空間、編碼等實務問題。

範例 XML(contact.xml)

<?xml version="1.0" encoding="UTF-8"?>
<contact id="43956">
  <personal>
    <name>
      <first>John</first>
      <middle>Q</middle>
      <last>Doe</last>
    </name>
    <title>Senior Manager</title>
    <employer>National Corp</employer>
    <dob>1971-12-22</dob>
  </personal>
  <contactInfo>
    <email type="work">john.doe@national.com</email>
    <phone type="mobile">+1-555-0199</phone>
  </contactInfo>
</contact>

遞歸遍歷所有節點(含屬性、文字)

<?php
function walkDomNode(\DOMNode $node, int $depth = 0): void
{
    $indent = str_repeat('  ', $depth);

    switch ($node->nodeType) {
        case XML_ELEMENT_NODE:
            echo "{$indent}元素: <{$node->nodeName}>\n";
            // 輸出屬性
            if ($node->hasAttributes()) {
                foreach ($node->attributes as $attr) {
                    echo "{$indent}  屬性: {$attr->name} = \"{$attr->value}\"\n";
                }
            }
            break;

        case XML_TEXT_NODE:
            $text = trim($node->nodeValue);
            if ($text !== '') {
                echo "{$indent}文字: \"{$text}\"\n";
            }
            break;

        case XML_CDATA_SECTION_NODE:
            echo "{$indent}CDATA: {$node->nodeValue}\n";
            break;

        case XML_COMMENT_NODE:
            echo "{$indent}註解: {$node->nodeValue}\n";
            break;
    }

    // 遞歸處理子節點
    if ($node->hasChildNodes()) {
        foreach ($node->childNodes as $child) {
            walkDomNode($child, $depth + 1);
        }
    }
}

// 載入並遍歷
$dom = new DOMDocument();
$dom->load('contact.xml'); // 或 loadXML($string)

echo "<pre>\n";
walkDomNode($dom->documentElement); // 從根元素開始
echo "</pre>\n";
?>

輸出結果範例

元素: <contact>
  屬性: id = "43956"
  元素: <personal>
    元素: <name>
      元素: <first>
        文字: "John"
      元素: <middle>
        文字: "Q"
      元素: <last>
        文字: "Doe"
    元素: <title>
      文字: "Senior Manager"
    ...

進階:使用 DOMXPath 精準查詢

<?php
$xpath = new DOMXPath($dom);

// 1. 取得所有 email 節點
$emails = $xpath->query('//email');
foreach ($emails as $email) {
    echo "Email: {$email->nodeValue} (類型: {$email->getAttribute('type')})\n";
}

// 2. 取得特定路徑的文字
$firstName = $xpath->evaluate('string(/contact/personal/name/first)');
echo "First Name: $firstName\n";

// 3. 含命名空間查詢(需註冊前綴)
// $xpath->registerNamespace('ns', 'https://example.com/ns');
// $nodes = $xpath->query('//ns:element');
?>

常見問題與解決方案

問題解決方法
載入報錯 "Entity not defined"$dom->substituteEntities = true; 或預先定義實體
中文亂碼確保 XML 宣告 encoding="UTF-8",PHP 腳本檔案也為 UTF-8 無 BOM
大檔案記憶體不足改用 XMLReader(拉式解析器),逐節點讀取,不建立完整 DOM 樹
預設移除空白文字節點$dom->preserveWhiteSpace = false;(預設 true),配合 $dom->formatOutput = true; 美化輸出
命名空間查詢失效必須用 registerNamespace() 註冊前綴,XPath 中使用前綴

XMLReader 串流式遍歷(大檔案適用)

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

while ($reader->read()) {
    switch ($reader->nodeType) {
        case XMLReader::ELEMENT:
            echo "開始元素: {$reader->name}";
            if ($reader->hasAttributes) {
                while ($reader->moveToNextAttribute()) {
                    echo " {$reader->name}=\"{$reader->value}\"";
                }
                $reader->moveToElement(); // 移回元素
            }
            echo "\n";
            break;
        case XMLReader::TEXT:
        case XMLReader::CDATA:
            $text = trim($reader->value);
            if ($text) echo "文字: $text\n";
            break;
        case XMLReader::END_ELEMENT:
            echo "結束元素: {$reader->name}\n";
            break;
    }
}
$reader->close();
?>

掌握 DOMDocument 與 XMLReader 兩大工具,即可應對從設定檔解析到大型 XML 資料交換的所有場景。

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