現代 Web 開發中,XML 與 JSON 是兩大主流資料交換格式。PHP 內建 `SimpleXML` 與 `json_encode/decode` 提供強大支援,本文整理雙向轉換的完整實作與注意事項。
<?xml version="1.0" encoding="UTF-8"?>
<humans>
<zhangying>
<name>張三</name>
<sex>男</sex>
<old>26</old>
</zhangying>
<tank>
<name>tank</name>
<sex>
<hao>yes</hao>
<aaaa>no</aaaa>
</sex>
<old>26</old>
</tank>
</humans>
/**
* XML 轉 JSON
* @param string $source XML 字串或檔案路徑
* @return string JSON 字串
*/
function xml_to_json($source) {
// 判斷是檔案路徑還是 XML 字串
if (is_file($source)) {
$xmlObj = simplexml_load_file($source);
} else {
$xmlObj = simplexml_load_string($source);
}
// PHP 5.2+ 內建 json_encode
return json_encode($xmlObj, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
}
{
"zhangying": {
"name": "張三",
"sex": "男",
"old": "26"
},
"tank": {
"name": "tank",
"sex": {
"hao": "yes",
"aaaa": "no"
},
"old": "26"
}
}
/**
* JSON 轉 XML
* @param string $source JSON 字串
* @param string $charset 編碼
* @return string XML 字串
*/
function json_to_xml($source, $charset = 'utf-8') {
if (empty($source)) return false;
$array = json_decode($source, true); // true = 關聯陣列
$xml = '<?xml version="1.0" encoding="' . $charset . '"?>';
$xml .= json_to_xml_recursive($array);
return $xml;
}
function json_to_xml_recursive($data) {
$xml = '';
foreach ($data as $key => $value) {
$xml .= "<$key>";
if (is_array($value) || is_object($value)) {
$xml .= json_to_xml_recursive($value); // 遞迴處理巢狀結構
} else {
$xml .= htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); // 防止特殊字元破壞 XML
}
$xml .= "</$key>";
}
return $xml;
}
| 議題 | 說明 | 解決方案 |
|---|---|---|
| XML 屬性 | SimpleXML 轉 JSON 會丟失屬性(如 ` | 需自訂遞迴函數保留 `@attributes` |
| CDATA 區段 | SimpleXML 預設展開 CDATA | 使用 `LIBXML_NOCDATA` 旗標 |
| 命名空間 | 複雜 XML 命名空間處理困難 | 改用 DOMDocument 處理 |
| 數值型別 | JSON 數值無引號,XML 全是字串 | 轉回 XML 時皆為字串,需自行型別轉換 |
function json_to_xml_advanced($data, $rootName = 'root') {
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$root = $dom->createElement($rootName);
$dom->appendChild($root);
build_xml($dom, $root, $data);
return $dom->saveXML();
}
function build_xml($dom, $parent, $data) {
foreach ($data as $key => $value) {
if (is_numeric($key)) $key = 'item'; // 數值索引轉為 item
if (is_array($value) || is_object($value)) {
// 檢查是否為屬性陣列
if (isset($value['@attributes']) && is_array($value['@attributes'])) {
$elem = $dom->createElement($key);
foreach ($value['@attributes'] as $attrKey => $attrVal) {
$elem->setAttribute($attrKey, $attrVal);
}
if (isset($value['@value'])) {
$elem->appendChild($dom->createTextNode($value['@value']));
}
build_xml($dom, $elem, array_diff_key($value, ['@attributes'=>1, '@value'=>1]));
} else {
$elem = $dom->createElement($key);
build_xml($dom, $elem, $value);
}
$parent->appendChild($elem);
} else {
$elem = $dom->createElement($key, htmlspecialchars($value, ENT_QUOTES, 'UTF-8'));
$parent->appendChild($elem);
}
}
}
PHP 處理 XML/JSON 轉換非常便利,`SimpleXML` 配合 `json_encode` 可快速完成基本轉換。但實務上常遇到屬性、CDATA、命名空間等複雜結構,建議根據專案需求選擇 `SimpleXML`(簡單結構)或 `DOMDocument`(複雜結構)實作更健壯的轉換器。