PHP中如何解析带多命名空间的SOAP请求并转为数组或JSON
SOAP报文转数组/JSON解决方案
直接调用simplexml_load_string后转JSON返回空,是因为SOAP报文携带多个命名空间,SimpleXML默认不会自动导出命名空间下的节点内容。使用支持命名空间的自定义转换函数即可解决,具体实现如下:
完整实现代码
/** * 支持命名空间的XML转数组函数 * @param SimpleXMLElement $xml 加载后的XML对象 * @return array|string */ function xmlToArray(SimpleXMLElement $xml) { $result = []; // 提取当前节点属性 if ($attrs = $xml->attributes()) { foreach ($attrs as $key => $val) { $result['@attributes'][$key] = (string)$val; } } // 遍历所有命名空间的子节点 $namespaces = $xml->getDocNamespaces(true); foreach ($namespaces as $nsPrefix => $nsUri) { foreach ($xml->children($nsUri) as $childKey => $childNode) { // 节点名默认携带命名空间前缀避免冲突,不需要可去掉前缀直接用$childKey $nodeKey = $nsPrefix ? "{$nsPrefix}:{$childKey}" : $childKey; $childArr = xmlToArray($childNode); // 处理同标签名多节点的数组兼容 if (isset($result[$nodeKey])) { if (!is_array($result[$nodeKey]) || !isset($result[$nodeKey][0])) { $result[$nodeKey] = [$result[$nodeKey]]; } $result[$nodeKey][] = $childArr; } else { $result[$nodeKey] = $childArr; } } } // 提取节点文本内容 $text = trim((string)$xml); if (empty($result)) { return $text; } if ($text !== '') { $result['@value'] = $text; } return $result; } // 调用示例 // 你的SOAP报文字符串 $soapXml = <<<XML <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <wsse:Security xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soap:mustunderstand="1"> <wsse:UsernameToken> <wsse:Username>username</wsse:Username> <wsse:Password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#passwordtext">secret</wsse:Password> </wsse:UsernameToken> </wsse:Security> </soap-env:Header> <soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <OTA_HotelResNotifRQ xmlns="http://www.opentravel.org/OTA/2003/05" Version="1.0" EchoToken="4528545b-f875-5c77-9205-22631b68f15a" ResStatus="Commit" TimeStamp="2018-07-31T01:16:16Z"> ... </OTA_HotelResNotifRQ> </soap-env:Body> </soap-env:Envelope> XML; // 加载XML,含CDATA请加LIBXML_NOCDATA参数 $xmlObj = simplexml_load_string($soapXml); $soapArray = xmlToArray($xmlObj); // 转JSON输出 $soapJson = json_encode($soapArray, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
访问示例
转换后可直接通过键名访问所有内容:
- 获取用户名:
$soapArray['soap-env:Header']['wsse:Security']['wsse:UsernameToken']['wsse:Username'] - 获取业务节点版本号:
$soapArray['soap-env:Body']['OTA_HotelResNotifRQ']['@attributes']['Version']
内容的提问来源于stack exchange,提问作者Edi 0
相关产品推荐
相关产品推荐

