我有另外一个与此相关的问题,但现在我正在尝试更直接地使用SoapVar,我发现这是一个不同的问题。 我正在使用UPS肥皂率报价webservice,他们有多个xml命名空间XSD文件,用于单一费率请求:
xmlns:common="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0"
xmlns:rate="http://www.ups.com/XMLSchema/XOLTWS/Rate/v1.1"
xmlns:upss="http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0"
在php中构建数据结构时,似乎分别为它们分配ns1,ns2和ns3。
问题似乎是基于xmlns:common和xmlns:rate都具有名为CodeDescriptionType的相同数据结构这一事实。当然,这是一种通用类型,它们似乎在整个请求和响应中反复使用,甚至偶尔会在它们吐出的错误消息中使用,只是在不同的元素名称下。
我遇到的问题是,我是否构建了请求的对象表示,或者是否逐段构建每个分支,每个子分支具有不同的'SoapVar'实例,每个子分支专门为每个子分支命名xml命名空间,如当我通过SoapClient(或更具体的__soapCall)传递数据时,PHP似乎用ns1 / ns2 / ns3填充命名空间,然后在它们应该是ns2(速率)时错误地将CodeDescriptionTypes指定为ns1(通用)
common.xsd :(相关部分)
<xsd:complexType name="CodeDescriptionType">
<xsd:sequence>
<xsd:element name="Code" type="xsd:string"/>
<xsd:element name="Description" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
RateWebServiceSchema.xsd :(相关部分)
<xsd:complexType name="CodeDescriptionType">
<xsd:sequence>
<xsd:element name="Code" type="xsd:string"/>
<xsd:element minOccurs="0" name="Description" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
根据我构建数据的方式,我使用PHP工具获得两个结果中的一个。如果我将它全部创建为一个大的数据结构并将其传递到__soapCall或首先通过SoapVar转换,我会得到外部包装错误名称以及内容(应该是ns2):
<ns1:PickupType>
<ns1:Code>01</ns1:Code>
</ns1:PickupType>
<ns1:CustomerClassification>
<ns1:Code>00</ns1:Code>
</ns1:CustomerClassification>
如果我尝试为使用此元素类型或其继承版本的任何内容显式创建SoapVar,我最终会将内部部分误命名为:
<ns2:PickupType>
<ns1:Code>01</ns1:Code>
</ns2:PickupType>
<ns2:CustomerClassification>
<ns1:Code>00</ns1:Code>
</ns2:CustomerClassification>
有没有人知道是否有一个解决方法,使用soap内置函数,这将允许您确保它在它构建的xml中分配它们时正确解释名称空间?我的猜测是,当它创建组合元素定义的某种数组或属性列表时,键是冲突的,并且只有公共版本保留在用于构建xml的最终数据中。我没有在classmap文档中看到任何内容,如果你可以通过命名空间拆分它们。 我发现获得'正确'输出的唯一方法是首先生成一个测试,看看如何通过php'重命名'命名空间(例如ns1为common,ns2为rate),然后手动构建任何CodeDescriptionTypes在将xmlns:rate命名空间传递给SoapVar之前,在xmlns:rate命名空间下:
/**
* @param string $code
* @param null|string $desc
* @param string $elem
* @return \SoapVar
*/
public static function getRaw($code, $desc=null, $elem='CodeDescription') {
$xml = sprintf("<ns2:%s>", $elem);
$xml .= sprintf("<ns2:Code>%s</ns2:Code>", $code);
if(!empty($desc))
$xml .= sprintf("<ns2:Description>%s</ns2:Description>", $desc);
$xml .= sprintf("</ns2:%s>", $elem);
return new \SoapVar($xml, XSD_ANYXML, $elem);
}
然后,如果我想将上面的两个元素定义为我更大的数据结构的一部分,我会做类似的事情:
// pickup information
$req->PickupType = Soap\rate\CodeDescriptionType::getRaw("01", null, 'PickupType');
// customer classification
$req->CustomerClassification = Soap\rate\CodeDescriptionType::getRaw("00", null, 'CustomerClassification');
这是一个丑陋的解决方案,因为如果由于任何原因xsd或wsdl文件应该更改和/或修改名称空间的php处理使得速率命名空间不再最终为'ns2',它必然会中断。有什么建议吗?