test.xml<?xml version="1.0" encoding="utf-8"?>
<books>
<book>
<author>Jack Herrington</author>
<title>PHP Hacks</title>
<publisher>O'Reilly</publisher>
</book>
<book>
<author>Jack Herrington</author>
<title>Podcasting Hacks</title>
<publisher>O'Reilly</publisher>
</book>
</books>
<?php
$doc = new DOMDocument();
$doc->load('test.xml');
foreach ($doc->getElementsByTagName('book') as $book) {
$author = $book->getElementsByTagName('author')->item(0)->nodeValue;
$title = $book->getElementsByTagName('title')->item(0)->nodeValue;
$publisher= $book->getElementsByTagName('publisher')->item(0)->nodeValue;
echo "Title: $title <br> Author: $author <br> Publisher: $publisher<hr>";
}
?>
<?php
$books = [
['title'=>'PHP Hacks', 'author'=>'Jack Herrington', 'publisher'=>"O'Reilly"],
['title'=>'Podcasting Hacks', 'author'=>'Jack Herrington', 'publisher'=>"O'Reilly"],
];
$doc = new DOMDocument();
$doc->formatOutput = true; // 縮進美化
$root = $doc->createElement('books');
$doc->appendChild($root);
foreach ($books as $b) {
$book = $doc->createElement('book');
foreach (['author','title','publisher'] as $tag) {
$el = $doc->createElement($tag);
$el->appendChild($doc->createTextNode($b[$tag]));
$book->appendChild($el);
}
$root->appendChild($book);
}
$doc->save('books.xml'); // 或 echo $doc->saveXML();
?>
優點:API 直觀、自動保證 well-formed、支援 XPath。
缺點:需將整個文檔載入內存,大文檔易 OOM。
<?php
$g_books = []; $g_elem = null;
function startElement($parser, $name, $attrs) {
global $g_books, $g_elem;
if ($name === 'BOOK') $g_books[] = [];
$g_elem = $name;
}
function endElement($parser, $name) {
global $g_elem; $g_elem = null;
}
function textData($parser, $text) {
global $g_books, $g_elem;
if (in_array($g_elem, ['AUTHOR','TITLE','PUBLISHER'])) {
$g_books[count($g_books)-1][$g_elem] = $text;
}
}
$parser = xml_parser_create();
xml_set_element_handler($parser, 'startElement', 'endElement');
xml_set_character_data_handler($parser, 'textData');
$fp = fopen('test.xml', 'r');
while ($data = fread($fp, 4096)) {
xml_parse($parser, $data);
}
fclose($fp);
xml_parser_free($parser);
foreach ($g_books as $b) {
echo "{$b['TITLE']} - {$b['AUTHOR']} - {$b['PUBLISHER']}\n";
}
?>
關鍵:$g_elem 追蹤當前標籤,$g_books 累積結果。內存佔用恆定,與文檔大小無關。
<?php
$xml = file_get_contents('test.xml');
preg_match_all('/<book>(.*?)<\/book>/s', $xml, $blocks);
foreach ($blocks[1] as $block) {
preg_match('/<author>(.*?)<\/author>/', $block, $a);
preg_match('/<title>(.*?)<\/title>/', $block, $t);
preg_match('/<publisher>(.*?)<\/publisher>/', $block, $p);
echo "{$t[1]} - {$a[1]} - {$p[1]}\n";
}
?>
⚠️ 風險:屬性順序變更、CDATA、命名空間、巢狀標籤均會導致匹配失效。嚴禁解析不可信輸入。
<?php
$books = [
['title'=>'PHP Hacks', 'author'=>'Jack Herrington', 'publisher'=>"O'Reilly"],
['title'=>'Podcasting Hacks', 'author'=>'Jack Herrington', 'publisher'=>"O'Reilly"],
];
?>
<books>
<?php foreach ($books as $b): ?>
<book>
<title><?= htmlspecialchars($b['title']) ?></title>
<author><?= htmlspecialchars($b['author']) ?></author>
<publisher><?= htmlspecialchars($b['publisher']) ?></publisher>
</book>
<?php endforeach; ?>
</books>
注意:必須自行 htmlspecialchars 轉義,否則極易產生非法 XML。
| 場景 | 推薦 | 理由 |
|---|---|---|
| 配置文件、RSS、API 響應(< 10MB) | DOM / SimpleXML | 開發效率高,代碼可讀性強 |
| 海量數據導入/導出(> 100MB) | SAX / XMLReader | 恆定內存,流式處理 |
| 極簡佈局、無屬性、可信輸入 | 模板內嵌 | 零依賴,直觀 |
| 歷史系統兼容、無擴展權限 | Regex(最後手段) | 僅作兜底,嚴加測試 |