PHP 產生 XML 給 Flash 讀取:編碼聲明與實際編碼不符的完整解決之道
Flash 讀取外部 XML 時若出現中文亂碼,核心原因通常在於 XML 宣告的編碼與檔案實際編碼不一致。本文系統分析四大典型情境並給出通用解決策略。
關鍵知識點:System.useCodePage
Flash Player 靜態屬性 `System.useCodePage` 決定如何解讀外部文字檔:
- false (預設):假設外部檔為 UTF-8,直接以 UTF-8 解碼。
- true:使用系統預設代碼頁(中文 Windows 為 CP936/GBK)解碼。
AS3 寫法:`import flash.system.System; System.useCodePage = true;`
四大常見情境與對策
情境一:XML 內容確無誤,但編碼聲明為 UTF-8,檔案實為 ANSI/GBK
Firefox 可正常顯示,IE/Flash 卻報錯或亂碼。
解法:
- 將 XML 宣告改為 `encoding="GB2312"` 並設 `System.useCodePage=true`;
- 或用記事本「另存新檔」為真正的 UTF-8 檔案。
情境二:PHP 原始碼為 ANSI,用 DOMDocument 產生 XML
$dom = new DomDocument('1.0', 'UTF-8'); // 僅修改宣告
$dom->saveXML(); // 實際輸出編碼仍為 ANSI(跟隨 PHP 檔案編碼)
導致「聲明 UTF-8,實際 ANSI」的假象。
解法:
- 將 PHP 檔案另存為 UTF-8 無 BOM 格式(推薦);
- 或生成後以字串替換將宣告改為 GB2312:
`$xml = str_replace('encoding="UTF-8"', 'encoding="GB2312"', $dom->saveXML());`
情境三:DOMDocument 不支援 GB2312 直接寫入中文
`new DomDocument('1.0', 'GB2312')` 會拋出 `output conversion failed` 錯誤。
解法:同上,生成 UTF-8 宣告的 XML 後,替換宣告為 GB2312,實際內容保持 ANSI/GBK,Flash 設 `useCodePage=true` 即可正常讀取。
情境四:通用最佳實踐(推薦)
- PHP 檔案統一使用 UTF-8 無 BOM 編碼儲存。
- DOMDocument 宣告 `new DomDocument('1.0', 'UTF-8')`。
- 輸出前發送正確標頭:`header('Content-Type: application/xml; charset=utf-8');`
- Flash 端保持 `System.useCodePage = false`(預設)。
- 全鏈路 UTF-8,零轉碼、零聲明偽裝,相容 IE/FF/Chrome/Flash 所有客戶端。
程式碼範本
<?php
// 1. 確保本檔為 UTF-8 無 BOM
header('Content-Type: application/xml; charset=utf-8');
$dom = new DomDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$root = $dom->createElement('data');
$dom->appendChild($root);
$item = $dom->createElement('item', '中文測試內容');
$root->appendChild($item);
echo $dom->saveXML();
// 輸出為真正的 UTF-8 XML,宣告與內容完全一致
?>
避坑提醒
- 編輯器(ZendStudio、PhpStorm、VS Code)需設定預設編碼為 UTF-8,避免無意中以 ANSI 開啟/儲存。
- 輸出 XML 前務必發送 `Content-Type` 標頭,瀏覽器/Flash 才會依標頭而非內容猜測編碼。
- 若歷史專案無法全面轉 UTF-8,採用「生成後替換宣告」作為過渡方案,但需嚴格測試各客戶端相容性。