我正在尝试为soap请求添加一些属性.上评分最高PHP.net评论(http://php.net/manual/en/soapvar.soapvar.php),并在这里和这里的SO都说着同样的事情:
$param = array(
    "_" => 'value',
    'attrName' => 'attributeName'
);
$p = new SoapVar($param, SOAP_ENC_OBJECT);
应该回来
<param attrName="attributeName">value</param>
哪个会很棒,除非我运行那段代码,我得到这个XML:
<param>
    <_>value</_>
    <attrName>attributeName</attrName>
</param>
这显然是错的.当然,我不是世界上唯一遇到这个问题的人吗?自2011年以来,关于这一点功能的文档是否发生了变化?
是的,您不是唯一遇到此问题的人 - 我已经看到无数帖子,其中人们声称使用 SOAP_ENC_OBJECT 传递给 SoapVar 的数组解决了该问题,而其他人则在同一帖子中声称另有说法。文档并不清楚原因(除了我一年前在 php.net 评论部分的帖子)。
面对同样的问题,我阅读了 PHP SOAP 扩展的来源。基本上你使用的语法是绝对正确的:
$param = array(
    "_" => 'value',
    'attrName' => 'attributeName'
);
$p = new SoapVar($param, SOAP_ENC_OBJECT);
文档没有说:这种语法可能会产生两种不同的结果(事实上甚至更多:PHP SOAP 可以用八种不同的方式表达它)。正如您可能看到的,上面的代码是模棱两可的:上面的代码中是什么说 'attrName' 是一个属性而不是一个元素?没有。上面的代码只是没有足够的信息量让 SoapClient 来决定“attrName”是什么,所以它默认为“一个元素”。
SoapClient 可以在两种模式下运行:非 WSDL 和 WSDL。在前一种模式下,您永远不会得到您想要的结果:SoapClient 依赖类型信息将数组元素转换为属性。由于非 WSDL 模式中不存在类型信息,因此 SoapClient 将提供的数组表示为一组元素 - 正是您得到的。在 WSDL 模式中存在类型信息,因此 SoapClient 知道元素和属性名称,并且可以将它们与数组索引进行匹配。所以如果你想要你的属性,你必须让你的 SoapClient 处于 WSDL 模式。
基本上,为了实现您想要的,您需要在 <xsd:schema> 块的适当部分中使用 <xsd:attribute name="attrName" type="xsd:string"/> 文档/文字模式下的 WSDL 文件。
有些人声称属性数组使用成功而另一些人说“它不起作用”的原因仅在于他们的设置:有些人有 WSDL 文件要使用,有些人只是试图执行 new SoapClient(null, array(. ..)); (这当然辜负了他们的期望)
目前我正在使用该DOMDocument对象来创建节点。希望有一种更简单的方法,但为了回答这个问题并提供解决方法,这里是:
$dom = new DOMDocument("1.0", "utf-8");
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$param = $dom->createElement('param');
$paramAttr = $dom->createAttribute('attrName');
$paramAttr->value = "attributeName";
$param->value = "value";
$param->appendChild($paramAttr);
$dom->appendChild($param);
$soap->param = new SoapVar($dom->saveXML($dom->documentElement), XSD_ANYXML);
所以不太理想。另一种方法是自己编写 XML:
$soap->param = new SoapVar("<param attrName='attributeName'>value</param>", XSD_ANYXML);
我不喜欢这两种方式,但当你有最后期限时,你就会选择有效的方式。
| 归档时间: | 
 | 
| 查看次数: | 2801 次 | 
| 最近记录: |