PHP中数组转XML的三种实现方式对比与使用
在PHP开发中,将数据结构序列化为XML是常见的后端需求。由于PHP标准库提供了多种XML处理扩展,开发者通常会遇到不同的实现思路。本文将梳理并修正几段经典的数组转XML代码,涵盖SimpleXML面向对象操作、DOMDocument节点构建以及基础递归逻辑,帮助理解不同写法在处理嵌套数组和非法标签名时的策略。
方法一:基于SimpleXML的面向对象封装
这种方法利用 SimpleXMLElement 构建对象树,最后转换为字符串。其特点在于自动处理XML头,并通过正则表达式清洗Key以确保符合XML命名规范。
第1步:定义ArrayToXML类
该实现包含一个静态方法 toXml,支持递归遍历多维数组。需要注意以下几点逻辑:
- 兼容性设置:关闭Zend兼容模式,避免旧版PHP抛出警告。
- 根节点初始化:当传入
$xml为null时,创建根节点对象。 - 键名清洗:若Key为数字,则替换为
unknownNode_前缀;若包含非字母数字字符,通过正则去除,以保证生成的XML合法。 - 值处理:子元素仍为数组时递归调用;否则使用
htmlentities转义后添加为文本节点。
class ArrayToXML
{
public static function toXml($data, $rootNodeName = 'data', $xml=null)
{
// 确保 SimpleXML 正常工作
if (ini_get('zend.ze1_compatibility_mode') == 1) {
ini_set ('zend.ze1_compatibility_mode', 0);
}
if ($xml == null) {
$xml = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$rootNodeName />");
}
foreach($data as $key => $value) {
// 处理数字键
if (is_numeric($key)) {
$key = "unknownNode_". (string) $key;
}
// 清洗非法字符
$key = preg_replace('/[^a-z]/i', '', $key);
if (is_array($value)) {
$node = $xml->addChild($key);
// 递归处理子数组
ArrayToXML::toXml($value, $rootNodeName, $node);
} else {
// 转义特殊字符并添加节点
$value = htmlentities($value);
$xml->addChild($key,$value);
}
}
return $xml->asXML();
}
}
方法二:基于DOMDocument的标准API操作
相比SimpleXML,DOMDocument 提供了更底层的节点控制能力。此函数采用默认参数设计,使其可以独立运行,也可作为部分DOM结构的一部分。
第2步:编写arrtoxml递归函数
逻辑核心在于判断 $dom 和 $item 是否存在,不存在则初始化为新的文档对象和根节点。对于每个数组元素,生成对应的Element节点:
- 如果Value不是数组,则创建Text节点并附加到Element节点。
- 如果Value是数组,则将当前Element作为父节点继续递归调用。
function arrtoxml($arr,$dom=0,$item=0){
if (!$dom){
$dom = new DOMDocument("1.0");
}
if(!$item){
$item = $dom->createElement("root");
$dom->appendChild($item);
}
foreach ($arr as $key=>$val){
// 如果key是数字,统一命名为 item
$tagName = is_string($key)?$key:"item";
$itemx = $dom->createElement($tagName);
$item->appendChild($itemx);
if (!is_array($val)){
$text = $dom->createTextNode($val);
$itemx->appendChild($text);
}else {
// 递归处理子节点
arrtoxml($val,$dom,$itemx);
}
}
return $dom->saveXML();
}
方法三:自定义递归字符串拼接
第三种方式不依赖特定的XML扩展对象,而是直接通过字符串拼接生成XML结构。这种方式轻量,但缺乏严格的DOM校验,且需手动管理全局变量控制层级缩进或结构标记。
第3步:配置array_Xml处理逻辑
使用 $elementLevel 全局变量跟踪深度。当Key为数字时,复用上一级Key名(这在某些特定JSON转XML场景下有用,但需注意语义准确性)。通过 startElement 和 endElement 包裹内容,递归生成闭合标签。
$elementLevel = 0 ;
function array_Xml($array, $keys = '')
{
global $elementLevel;
if(!is_array($array))
{
if($keys == ''){
return $array;
}else{
return "\n<$keys>" . $array . "</$keys>";
}
}else{
foreach ($array as $key => $value)
{
$haveTag = true;
if (is_numeric($key))
{
$key = $keys;
$haveTag = false;
}
/** * 根层级处理 */
if($elementLevel == 0 )
{
$startElement = "<$key>";
$endElement = "</$key>";
}
$text .= $startElement."\n";
/** * 子层级处理 */
if(!$haveTag)
{
$elementLevel++;
$text .= "<$key>" . array_Xml($value, $key). "</$key>\n";
}else{
$elementLevel++;
$text .= array_Xml($value, $key);
}
$text .= $endElement."\n";
}
}
return $text;
}
应用示例:转换测试数组
以下是一个典型的员工信息多维数组结构,可用于验证上述方法的输出结果。注意观察嵌套的 employees 和重复的子键 employee。
<?php
$array = array(
"employees" => array(
"employee" => array(
array(
"name" => "name one",
"position" => "position one"
),
array(
"name" => "name two",
"position" => "position two"
),
array(
"name" => "name three",
"position" => "position three"
)
)
)
);
// 使用方法三进行转换测试
echo array_Xml($array);
?
总结与选择建议
以上三种代码片段均实现了从PHP数组到XML的转换,但在实际生产环境中请注意:
- 方法一(SimpleXML) 适合大多数常规场景,API简洁且自带编码处理,但对非法标签名的清洗力度较大(仅保留字母)。
- 方法二(DOMDocument) 是最稳健的选择,符合W3C标准,便于处理复杂的XML属性和名称空间(Namespace),推荐用于接口交互。
- 方法三(字符串拼接) 代码较长且依赖全局状态,易出错,除非有极特殊的格式要求,否则不建议直接使用,建议优先使用内置扩展。
以上就是PHP中将数组转成XML格式的实现代码的详细分析与比较,更多关于PHP数据处理技巧的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









