你能在php SoapClient中定义命名空间键/值吗?

时间:2016-10-19 16:11:23

标签: php soap xml-namespaces soap-client

我目前正在尝试为SoapClient实现一个包装器,以通过UPS Web服务处理Rate服务请求。我看到的一件事是它们似乎使用绑定到不同名称空间的单独模式,并且一些容器似乎在不同的名称空间中重复。 我不是100%确定php如何在wsdl中链接的两个不同模式文件中定义容器时使用什么命名空间,但它似乎工作一次,现在我收到错误并且唯一的事情我看到它是在返回错误的项目上定义了错误的命名空间。

尽管我可以看到,WSDL和Schema提供了获得正确信息所需的信息。 WSDL指向UPS包含的文件RateWebServicesSchema.xsd,用于UPS定义为命名空间' rate' (php自动生成&#ns;')并指向common.xsd for namespace' common' (php自动生成' ns1')

来自UPS的RateWebServicesSchema.xsd和common.xsd都包含复杂类型' CodeDescriptionType'作为一个例子(生成错误代码的元素正在使用的那个例子,所以我假设命名空间是问题)

<xsd:complexType name="CodeDescriptionType">
    <xsd:sequence>
        <xsd:element name="Code" type="xsd:string"/>
        <xsd:element name="Description" type="xsd:string"/>
    </xsd:sequence>
</xsd:complexType>

RateWebServicesSchema.xsd似乎告诉任何解释它的东西使用PickupType中子元素的速率命名空间:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:common="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0" xmlns:rate="http://www.ups.com/XMLSchema/XOLTWS/Rate/v1.1" xmlns:ups="http://www.ups.com/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.ups.com/XMLSchema/XOLTWS/Rate/v1.1" version="201607">
    <xsd:import namespace="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0" schemaLocation="common.xsd"/>
    <xsd:element name="RateRequest">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="common:Request"/>
                <xsd:element minOccurs="0" name="PickupType" type="rate:CodeDescriptionType"/>
                <xsd:element minOccurs="0" name="CustomerClassification" type="rate:CodeDescriptionType"/>
                <xsd:element name="Shipment" type="rate:ShipmentType"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
 [.....]

如上所述,php创建的信封定义为ns1,速率定义为ns2,但是当我通过__soapCall运行它时,得到的“拾取类型代码”缺失了#39;看看请求,我明白了:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:ns1="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0"
 xmlns:ns2="http://www.ups.com/XMLSchema/XOLTWS/Rate/v1.1"
 xmlns:ns3="http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0">
    <SOAP-ENV:Body>
        <ns2:RateRequest>
            <ns1:Request>
                <ns1:RequestOption>Shop</ns1:RequestOption>
                <ns1:TransactionReference />
            </ns1:Request>
            <ns2:PickupType xsi:type="ns1:CodeDescriptionType">
                <ns1:Code>01</ns1:Code>
                <ns1:Description />
            </ns2:PickupType>      [......]

请求是常见的&#39;所以它被正确显示为ns1,但代码/描述由于某种原因被指向ns1。

我无法追溯到的一个奇怪的事情是,它之前的某个时刻正确地分配它们,我不确定会发生什么/可能会改变以使它开始指向普通( ns1)而不是rate(ns2)名称空间。

所以这会产生一些问题。

首先(也是最重要的)是任何人都知道为什么php可能会分配错误的命名空间和/或我如何指导&#39; SoapClient使用特定的一个用于冗余命名的数据结构吗?

第二,为了便于调试和出于好奇心,无论如何都要为这些命名空间预先定义密钥,这样我就不必经常将ns1转换为常用或ns2转换率等等?

第三,我使用WSDLInterpreter v1.0生成模式的各种基于php的对象表示。它不是100%,所以,例如它没有建立一些共同的&#39;命名空间对象,我必须手动构建这些对象:Request和common:响应例如。显然,我无法在CodeDescriptionType的同一目录中创建多个对象。有没有办法使用PHP [如PHP命名空间?]来帮助区分肥皂使用什么和肥皂叫什么?也许一个phpdoc标签或什么?例如通过在特定于xml名称空间的目录中分隔php类来创建多个CodeDescription类型。 (这里只是广泛推测)

更新: 我在另一篇文章中发现,如果使用SoapVar创建传出Soap数据,则可以指定命名空间,因此我更改了我的代码,通过在添加给定分支时包装它们来构建传出数据的每个子分支。 SoapVar指定与该分支相关的命名空间。 虽然这似乎在某种程度上起作用,但它以一种奇怪的方式有点不一致。一些元素被正确地命名为namespace:type而其他元素被命名为namespace:type xsi:type =&#34; namespace:type&#34;冗余。

例如,上面的代码现在具有正确的命名空间,但显示如下:

<SOAP-ENV:Body>
    <ns2:RateRequest xsi:type="ns2:RateRequest">
        <ns1:Request xsi:type="ns1:Request">
            <ns1:RequestOption>Shop</ns1:RequestOption>
            <ns1:TransactionReference xsi:type="ns1:TransactionReference">
                <ns1:CustomerContext>Order  Rate </ns1:CustomerContext>
            </ns1:TransactionReference>
        </ns1:Request>
        <ns2:PickupType xsi:type="ns2:Pickup">
            <ns1:Code>01</ns1:Code>
            <ns1:Description/>
        </ns2:PickupType>

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题(尽管目前在TNTWS服务中工作,而不是RateWS,但很快就会解决)。我遇到了同样的错误,PHP将错误的名称空间分配给了看起来应该正确的内容。

我已经将WSDL文件中的PHP类生成到它们自己的名称空间(UPS \ TNTWS,UPS \ RateWS等)中。

这是与您遇到的相同问题失败的代码:

new ShipmentWeightType(
    new CodeDescriptionType('LBS', 'Pounds'),
    $weight
),

哪个制作的:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0"
                   xmlns:ns2="http://www.ups.com/XMLSchema/XOLTWS/tnt/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:ns3="http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0">
    [...]
    <SOAP-ENV:Body>
        <ns2:TimeInTransitRequest>
            [...]
            <ns2:ShipmentWeight>
                <ns2:UnitOfMeasurement xsi:type="ns1:CodeDescriptionType">
                    <ns1:Code>LBS</ns1:Code>
                    <ns1:Description>Pounds</ns1:Description>
                </ns2:UnitOfMeasurement>
                <ns2:Weight>5.14</ns2:Weight>
            </ns2:ShipmentWeight>
            <ns2:TotalPackagesInShipment>1</ns2:TotalPackagesInShipment>
        </ns2:TimeInTransitRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

这就是成功的地方

new ShipmentWeightType(
    new UOMCodeDescriptionType('LBS', 'Pounds'),
    $weight
),

生产:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0"
                   xmlns:ns2="http://www.ups.com/XMLSchema/XOLTWS/tnt/v1.0" xmlns:ns3="http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0">
    [...]
    <SOAP-ENV:Body>
        <ns2:TimeInTransitRequest>
            [...]
            <ns2:ShipmentWeight>
                <ns2:UnitOfMeasurement>
                    <ns2:Code>LBS</ns2:Code>
                    <ns2:Description>Pounds</ns2:Description>
                </ns2:UnitOfMeasurement>
                <ns2:Weight>5.14</ns2:Weight>
            </ns2:ShipmentWeight>
            <ns2:TotalPackagesInShipment>1</ns2:TotalPackagesInShipment>
        </ns2:TimeInTransitRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

显然,UOMCodeDescriptionType与CodeDescriptionType不同,使用错误的代码会破坏事物。