如何将Curl返回的SOAP XML响应转换为JSON?
问题:无法访问SOAP XML转换后的SimpleXMLElement节点值
场景复现
- 通过Curl获取SOAP格式XML响应:
$response = curl_exec($ch); curl_close($ch); dd($response);
响应字符串内容(部分):
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <SOAP-ENV:Body> <ns3:GetProductListResponse xmlns:ns3="http://xxx1"> <result> <status>success</status> </result> <products> <product> <currencyAmount>900.00</currencyAmount> <currencyType>1</currencyType> <displayPrice>900.00</displayPrice> <isDomestic>false</isDomestic> <id>557830715</id> <price>900.00</price> <productSellerCode>TSRT7777</productSellerCode> <approvalStatus>6</approvalStatus> ...
- 使用
simplexml_load_string()转换为SimpleXMLElement对象:
$response = curl_exec($ch); curl_close($ch); $xml = simplexml_load_string($response); dd($xml);
输出结果:
^ SimpleXMLElement {#435}
- 尝试直接访问节点值返回空字符串:
$status = (string)$xml->result->status; dd($status);
返回空,尝试simplexml_load_file()也无结果,目标是将XML转为JSON但受阻。
- 添加错误检测验证XML加载成功:
if ($xml === false) { dump("b"); foreach (libxml_get_errors() as $error) { dump($error->message); } dd("a"); } else { dd("c"); }
返回结果为"c",确认XML加载成功,但仍无法访问节点值。
解决方案
问题核心是XML命名空间未被正确处理,SOAP响应包含SOAP-ENV和ns3两个命名空间,直接通过节点名访问会忽略命名空间导致找不到节点,以下是两种可行解决方法:
方法1:通过children()指定命名空间逐层访问
// 获取SOAP Body节点(指定SOAP-ENV命名空间) $body = $xml->children('http://schemas.xmlsoap.org/soap/envelope/')->Body; // 获取业务响应节点(指定ns3命名空间) $responseNode = $body->children('http://xxx1')->GetProductListResponse; // 正常访问status节点 $status = (string)$responseNode->result->status; dd($status); // 输出"success"
方法2:注册命名空间前缀后用XPath查询
// 为命名空间注册易记前缀 $xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/'); $xml->registerXPathNamespace('ns3', 'http://xxx1'); // 使用XPath精准定位status节点 $statusNodes = $xml->xpath('//soap:Body/ns3:GetProductListResponse/result/status'); if (!empty($statusNodes)) { $status = (string)$statusNodes[0]; dd($status); // 输出"success" }
完整XML转JSON示例
$response = curl_exec($ch); curl_close($ch); // 开启内部错误捕获避免警告 libxml_use_internal_errors(true); $xml = simplexml_load_string($response); libxml_clear_errors(); if ($xml) { // 处理命名空间获取核心数据节点 $body = $xml->children('http://schemas.xmlsoap.org/soap/envelope/')->Body; $dataNode = $body->children('http://xxx1')->GetProductListResponse; // 先转JSON再转数组(解决SimpleXMLElement转数组的命名空间问题) $arrayData = json_decode(json_encode($dataNode), true); $jsonResult = json_encode($arrayData, JSON_PRETTY_PRINT); dd($jsonResult); }
内容的提问来源于stack exchange,提问作者kaann.gunerr
相关产品推荐
相关产品推荐

