我有另外一个与此相关的问题,但现在我正在尝试更直接地使用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) .

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,我最终会将内部部分命名为mis-namespaced:

<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在将它们传递给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',它必然会中断 . 有什么建议?