好吧,在花了几个小时之后,我终于明白了! 我不得不根据如下标签名称进行修改,在大多数情况下,我不得不使用 soap-env 而不是 SOAP.
$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->loadXML($response->Data);
$dom->formatOutput = true;
$XMLContent = $dom->saveXML();
$xml = simplexml_load_String($XMLContent, null, null, 'soap-env', true);
if(!$xml)
trigger_error("Encoding Error!", E_USER_ERROR);
$Results = $xml->children('soap-env',true);
foreach($Results->children('soap-env',true) as $fault){
if(strcmp($fault->getName(),'Fault') == 0){
trigger_error("Error occurred request/response processing!", E_USER_ERROR);
}
}
foreach($Results->children('wsse',true) as $nodes){
if(strcmp($nodes->getName(),'Security') == 0){
foreach($nodes->children('wsse',true) as $securityNodes){
if(strcmp($securityNodes->getName(),'BinarySecurityToken') == 0){
$tokenParsed = (string)$securityNodes;
}
}
}
}
这就是SOAP,一种使用XML语法的对象序列化格式。最佳解决方案是使用 SOAP 库。 PHP 对此有
ext/soap
。使用 XML 库会低一个级别。
XML 使用命名空间。名称空间是使用唯一的 URI 指定的。为了可读性/可维护性,XML 为 URI 定义了别名,并将它们用作节点名称的前缀。但是以下3个例子都应该读作
{http://schemas.xmlsoap.org/soap/envelope/}envelope
:
<soap-env:envelope xmlns::soap-env="http://schemas.xmlsoap.org/soap/envelope/"/>
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/>
<envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"/>
命名空间可以在任何元素节点上定义,因此它们甚至可以在单个文档中更改。这意味着您的代码不应该依赖于文档中的别名/前缀,而是名称空间 URI。
我强烈建议为使用的命名空间定义一个数组变量/常量。然后你可以使用 Xpath 和命名空间感知 DOM 方法(后缀
NS
)。
// used namespaces, the keys do NOT need to match the prefixes in the XML.
$xmlns = [
'soap' => 'http://schemas.xmlsoap.org/soap/envelope/',
'eb' => 'http://www.ebxml.org/namespaces/messageHeader',
'sec' => 'http://schemas.xmlsoap.org/ws/2002/12/secext'
];
$document = new DOMDocument();
$document->loadXML(getSoapXmlString());
$xpath = new DOMXpath($document);
// register your aliases for the namespaces
foreach ($xmlns as $alias => $uri) {
$xpath->registerNamespace($alias, $uri);
}
$token = $xpath->evaluate(
'string(//sec:security/sec:binarysecuritytoken)'
);
var_dump($token);
DOMXpath::evaluate()
允许 Xpath 表达式返回节点列表和标量值。如果将节点列表(由位置路径指定)转换为字符串,它将返回第一个节点的文本内容或空字符串。