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

PHP 生成 XML 時添加 CDATA 區塊的正確姿勢:DOMDocument 實戰指南

     編輯:PHP 相關知識

XML 中包含特殊字符(<、>、&、'、")、HTML 片段、JSON、腳本代碼時,直接作為文本節點會被轉義導致可讀性差、解析麻煩。CDATA 區塊(<![CDATA[ ... ]]>)可保持原始內容不被解析器處理。本文演示 DOMDocument::createCDATASection 正確用法與常見陷阱。

核心 API

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

// 建立根元素
$root = $dom->createElement('data');
$dom->appendChild($root);

// 普通文本節點(會自動轉義特殊字符)
$textNode = $dom->createTextNode('AT&T <tag> "quotes"');
$root->appendChild($textNode);

// CDATA 區塊(原樣保留,不轉義)
$cdata = $dom->createCDATASection('<script>alert("Hello & World")</script>');
$root->appendChild($cdata);

// 屬性節點(不支援 CDATA,需自行轉義)
$attr = $dom->createAttribute('json');
$attr->value = json_encode(['key' => 'value with & special']); // 屬性值自動轉義
$root->appendChild($attr);

// 輸出
header('Content-Type: application/xml; charset=utf-8');
echo $dom->saveXML();
/*
<?xml version="1.0" encoding="UTF-8"?>
<data>AT&T &lt;tag&gt; &quot;quotes&quot;<![CDATA[<script>alert("Hello & World")</script>]]><json json="{"key":"value with & special"}"/>
</data>
*/
?>

實戰場景:包裝 HTML 片段/JSON/模板

<?php
function buildArticleXml(array $article): string {
    $dom = new DOMDocument('1.0', 'UTF-8');
    $dom->formatOutput = true;
    
    $root = $dom->createElement('article');
    $dom->appendChild($root);
    
    // 簡單字段用文本節點
    $title = $dom->createElement('title', $article['title']);
    $root->appendChild($title);
    
    // 富文本內容用 CDATA
    $content = $dom->createElement('content');
    $cdata = $dom->createCDATASection($article['html_content']);
    $content->appendChild($cdata);
    $root->appendChild($content);
    
    // 結構化數據用 JSON + CDATA(避免雙重轉義)
    $meta = $dom->createElement('meta');
    $json = json_encode($article['meta'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $meta->appendChild($dom->createCDATASection($json));
    $root->appendChild($meta);
    
    return $dom->saveXML();
}

// 測試
$article = [
    'title' => 'PHP & XML',
    'html_content' => '<h1>標題</h1><p>包含 & 特殊字符</p>',
    'meta' => ['author' => '張三', 'tags' => ['php', 'xml'], 'views' => 123],
];
header('Content-Type: application/xml; charset=utf-8');
echo buildArticleXml($article);
?>

關鍵注意事項

場景處理方式原因
內容含 ]]>拆分為多個 CDATA:<![CDATA[...]]]]><![CDATA[>...]]>CDATA 內部不能出現結束標記
屬性值不可用 CDATA,用 createAttribute 自動轉義XML 規範屬性值不支援 CDATA
JSON 序列化JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES + CDATA避免 Unicode 轉義、斜槓轉義,保持可讀
大文本流式輸出XMLWriter + writeCData()DOMDocument 需全量構建樹,記憶體佔用大

XMLWriter 版(大文件/流式)

<?php
function streamArticleXml(array $article): void {
    header('Content-Type: application/xml; charset=utf-8');
    $writer = new XMLWriter();
    $writer->openMemory();
    $writer->setIndent(true);
    $writer->startDocument('1.0', 'UTF-8');
    
    $writer->startElement('article');
    
    $writer->writeElement('title', $article['title']);
    
    $writer->startElement('content');
    $writer->writeCData($article['html_content']);
    $writer->endElement(); // content
    
    $writer->startElement('meta');
    $json = json_encode($article['meta'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $writer->writeCData($json);
    $writer->endElement(); // meta
    
    $writer->endElement(); // article
    $writer->endDocument();
    
    echo $writer->outputMemory();
}
?>

解析端處理 CDATA

<?php
$xml = '<data><![CDATA[<b>Bold</b>]]></data>';

// simplexml_load_string 預設合併 CDATA 為文本
$simple = simplexml_load_string($xml);
echo (string)$simple->data; // 直接輸出:Bold

// DOMDocument 保留 CDATA 節點類型
$dom = new DOMDocument();
$dom->loadXML($xml);
foreach ($dom->documentElement->childNodes as $node) {
    if ($node->nodeType === XML_CDATA_SECTION_NODE) {
        echo "CDATA 內容: " . $node->data; // 獲取原始內容
    }
}
?>

總結

  • 文本節點:自動轉義,適合純文本、標題、屬性值
  • CDATA 區塊:保持原樣,適合 HTML、JSON、腳本、包含特殊字符的大段內容
  • DOMDocument:功能全、易用、適合中小文件
  • XMLWriter:流式、低記憶體、適合大文件/高併發
  • 屬性值:永不使用 CDATA,依賴自動轉義

正確使用 CDATA 能讓 XML 既符合規範又保持業務內容完整性,是構建高質量數據交換介面的關鍵技能。

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