
本文详解如何修改 array_to_xml() 函数,使数组中带 @value 和 @attributes 的重复键(如 kontakt)被正确转换为多个独立的同名 XML 标签(如 ...),而非嵌套结构。
本文详解如何修改 `array_to_xml()` 函数,使数组中带 `@value` 和 `@attributes` 的重复键(如 `kontakt`)被正确转换为多个独立的同名 xml 标签(如 `
在使用 SimpleXMLElement 将关联数组转为 XML 时,一个常见需求是:当数组中某个键(如 "kontakt")对应一个索引数组(即多个联系人项),且每项均含 @value 和 @attributes 时,应生成多个同名 XML 元素(如
原始函数的问题在于:它将整个 "kontakt" 数组作为嵌套结构递归处理,导致生成 、 这类非法标签名(XML 标签名不能以数字开头),违背了预期语义。
✅ 正确处理逻辑
核心思路是:对特定键(如 "kontakt")进行特例化处理——遍历其子项,为每一项单独创建
以下是优化后的通用实现(支持任意键名,不限于 "kontakt"):
function array_to_xml($data, &$xml_data, $specialKeys = ['kontakt']) {
foreach ($data as $key => $value) {
// 若当前键属于需展开的“重复键”列表,且值为索引数组
if (is_array($value) && in_array($key, $specialKeys) && !empty($value)) {
foreach ($value as $item) {
if (!isset($item['@value'])) continue;
// 创建新元素,名称为 $key(如 kontakt)
$element = $xml_data->addChild($key, $item['@value']);
// 注入属性(支持多属性,不限于 'typ')
if (isset($item['@attributes']) && is_array($item['@attributes'])) {
foreach ($item['@attributes'] as $attrName => $attrValue) {
$element->addAttribute($attrName, $attrValue);
}
}
}
}
// 其他键按常规递归处理
elseif (is_array($value)) {
$subnode = $xml_data->addChild($key);
array_to_xml($value, $subnode, $specialKeys);
}
else {
$xml_data->addChild($key, htmlspecialchars($value, ENT_XML1));
}
}
}
? 使用示例
$data = [
"kontakt" => [
1 => [
'@value' => '<a class="__cf_email__" data-cfemail="79181b1a39181b1a570915" href="/cdn-cgi/l/email-protection">[email protected]</a>',
'@attributes' => ['typ' => 'email'],
],
2 => [
'@value' => '3123453141',
'@attributes' => ['typ' => 'telefon'],
],
],
"name" => "John Doe",
];
$xml = new SimpleXMLElement('<root></root>');
array_to_xml($data, $xml, ['kontakt']);
echo $xml->asXML();
输出结果:
<?xml version="1.0"?><root><kontakt typ="email"><a class="__cf_email__" data-cfemail="79181b1a39181b1a570915" href="/cdn-cgi/l/email-protection">[email@example.com]</a></kontakt><kontakt typ="telefon">3123453141</kontakt><name>John Doe</name></root>
⚠️ 注意事项:
- htmlspecialchars() 被用于安全转义文本内容,防止 XML 特殊字符(如 标签),需改用 DOMDocument::createCDATASection() 或 SimpleXMLElement::addChild() 后手动追加 XML(见进阶方案)。
- @attributes 支持任意键值对(如 ['typ'=>'email', 'priority'=>'high']),代码已兼容多属性。
- 可通过 $specialKeys 参数灵活扩展其他需展开的键名(如 'phone', 'address')。
该方案兼顾可读性、健壮性与扩展性,彻底解决重复键展开难题,是生产环境中推荐的实践方式。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











