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

PHP XML 與陣列雙向轉換工具類

     編輯:PHP 綜合知識

API 整合、配置檔處理常需在 XML 與 PHP 陣列間轉換。本文提供兩個獨立工具:xml2array() 函數 (基於 PHP XML 解析器) 與 Array2Xml 類 (陣列生成 XML),支援屬性、CDATA、巢狀結構、重複標籤轉索引陣列。

XML → 陣列: xml2array()

function xml2array($xmlStr, $getAttributes = true, $priority = 'tag') {
    if (!$xmlStr) return [];
    $parser = xml_parser_create();
    xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    xml_parse_into_struct($parser, trim($xmlStr), $vals);
    xml_parser_free($parser);

    $result = [];
    $parents = [];
    $repeated = [];

    foreach ($vals as $v) {
        $tag = $v['tag'];
        $type = $v['type'];
        $level = $v['level'];
        $attrs = $v['attributes'] ?? [];
        $value = $v['value'] ?? null;

        if ($type == 'open') {
            $parents[$level-1] = &$result;
            if (!isset($result[$tag])) {
                $result[$tag] = [];
                $repeated[$tag . '_' . $level] = 1;
            } else {
                // 重複標籤轉為索引陣列
                if (!isset($result[$tag][0])) {
                    $result[$tag] = [$result[$tag]];
                }
                $result[$tag][] = [];
                $repeated[$tag . '_' . $level]++;
            }
            $last = $repeated[$tag . '_' . $level] - 1;
            $result = &$result[$tag][$last];
            if ($getAttributes && $attrs) $result['@attributes'] = $attrs;
        } elseif ($type == 'complete') {
            $item = $value;
            if ($getAttributes && $attrs) $item = ['@value' => $value, '@attributes' => $attrs];
            if (!isset($result[$tag])) {
                $result[$tag] = $item;
            } else {
                if (!isset($result[$tag][0])) $result[$tag] = [$result[$tag]];
                $result[$tag][] = $item;
            }
        } elseif ($type == 'close') {
            $result = &$parents[$level-1];
        }
    }
    return $result;
}

陣列 → XML: Array2Xml 類

class Array2Xml {
    private $xml = '\n';
    private $subItems = [];

    public function __construct(array $data) {
        $this->xml .= $this->build($data);
    }

    private function build(array $arr, $parentKey = '') {
        $out = '';
        foreach ($arr as $key => $val) {
            if (is_array($val)) {
                if (is_numeric($key)) {
                    $this->subItems = array_merge($this->subItems, [$parentKey]);
                    $out .= "<$parentKey>" . $this->build($val, $key) . "";
                } else {
                    $out .= "<$key>" . $this->build($val, $key) . "";
                }
            } else {
                // 屬性處理:@attributes 鍵
                if ($key === '@attributes') {
                    // 屬性應在父標籤輸出時處理,這裡簡化忽略
                } elseif ($key === '@value') {
                    $out .= htmlspecialchars($val, ENT_QUOTES, 'UTF-8');
                } else {
                    $out .= "<$key>" . htmlspecialchars($val, ENT_QUOTES, 'UTF-8') . "\n";
                }
            }
        }
        return $out;
    }

    public function __toString() {
        // 修正巢狀數字鍵導致的重複標籤
        foreach ($this->subItems as $tag) {
            $this->xml = str_replace("<$tag><$tag>", "<$tag>", $this->xml);
            $this->xml = str_replace("", "", $this->xml);
        }
        return $this->xml;
    }
}

使用範例

$xml = 'JohnadminJane';
$arr = xml2array($xml);
print_r($arr);
/*
Array
(
    [root] => Array
        (
            [user] => Array
                (
                    [0] => Array ([@attributes]=>Array([id]=>1), [name]=>John, [role]=>admin)
                    [1] => Array ([@attributes]=>Array([id]=>2), [name]=>Jane)
                )
        )
)
*/

$xmlObj = new Array2Xml($arr);
echo $xmlObj; // 輸出格式化 XML

生產環境建議

  • 複雜 XML (命名空間、DTD、XSD) 請用 DOMDocument / SimpleXMLElement 原生操作。
  • 大檔案串流解析用 XMLReader,避免記憶體爆炸。
  • 陣列轉 XML 推薦 spatie/array-to-xml 或 laminas/laminas-xml,支援屬性、CDATA、命名空間完整規格。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved