PHP多维数组转XML序列化失败 SOAP接口返回序列化错误求助
问题原因
- 自定义XML转换函数逻辑存在缺陷:原函数处理索引数组时,未按要求将每个子项包裹在
<item>标签中,同时变量$child的作用域逻辑错误,导致items节点下无法生成符合要求的子节点,服务端无法识别内容直接丢弃,返回空的items标签。 - 数组字段与WSDL定义的Schema不匹配:
- 根级
name字段为完整姓名,Schema要求拆分为name和surname两个独立字段 - 根级
where_from字段与Schema要求的from字段名不符 - 地址下的
vat_number字段与Schema要求的post_code字段名不符 items子数组的键为cook、clean,但Schema明确要求每个子项必须包含name、material两个字段,字段不匹配导致服务端序列化失败。
- 根级
修复方案
步骤1:调整数组字段匹配Schema要求
先把原始数组的字段转换为WSDL要求的格式:
// 你的原始数组 $original = [ "name" => "John Doe", "date" => "2021-11-30 00:00:00.000", "job" => "developer", "where_from" => "france", "address" => [ "country" => "france", "city" => "paris", "vat_number" => "123456" ], "items" => [ ["cook" => "spoon", "clean" => "vacuum"] ] ]; // 转换为符合Schema的数组 $matched = [ 'name' => explode(' ', $original['name'])[0], 'surname' => explode(' ', $original['name'])[1], 'job' => $original['job'], 'from' => $original['where_from'], 'address' => [ 'country' => $original['address']['country'], 'city' => $original['address']['city'], 'post_code' => $original['address']['vat_number'] ], 'items' => [ ['name' => 'spoon', 'material' => 'metal'], ['name' => 'vacuum', 'material' => 'plastic'] ] ];
步骤2:修复XML转换函数
修复原函数的索引数组处理逻辑和变量作用域问题:
function convertToXml($data, $name='root', &$doc=null, &$node=null){ if ($doc === null){ $doc = new DOMDocument('1.0','UTF-8'); $doc->formatOutput = TRUE; $node = $doc; } if (is_array($data)){ $parent = $doc->createElement($name); $node->appendChild($parent); foreach($data as $key => $value){ if (is_numeric($key)){ // 索引数组子项统一用item标签包裹 convertToXml($value, 'item', $doc, $parent); }else{ convertToXml($value, $key, $doc, $parent); } } }else{ $child = $doc->createElement($name); $child->appendChild($doc->createTextNode($data)); $node->appendChild($child); } if ($doc === $node) { return $doc->saveXML(); } }
可选优化方案
不需要手动拼接XML,直接使用PHP内置的SoapClient类处理,它会自动根据WSDL的Schema完成数组序列化,避免手动转换的格式错误:
try { $client = new SoapClient('你的服务WSDL地址', [ 'encoding' => 'UTF-8', 'exceptions' => true ]); $response = $client->Person($matched); var_dump($response); } catch (SoapFault $e) { var_dump($e->getMessage()); }
内容的提问来源于stack exchange,提问作者user12532474
相关产品推荐
相关产品推荐

