douyueju2912 2016-10-19 16:11
浏览 240

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

I'm currently trying to implement a wrapper for SoapClient to handle Rate service requests via the UPS web services. One of the things I see off the bat is that they seem to use separate schemas tied to different name spaces and some containers seem to repeat in the different namespaces. I'm not 100% sure how php figures out what namespace to use when a container is defined in two different schema files linked in from the wsdl, but it seemed to work once, and now I am getting errors and the only thing I see is that it is defining the wrong namespace on the item returning the error.

As near as I can see, the WSDL and Schema provide the information necessary to get the right one. The WSDL points to the UPS included files RateWebServicesSchema.xsd for what UPS defines as namespace 'rate' (php auto-generates 'ns2') and points to common.xsd for namespace 'common' (php auto-generates 'ns1')

both the RateWebServicesSchema.xsd and the common.xsd from UPS include a complex type 'CodeDescriptionType' as one example (the one that is being used by the element generating a 'code missing' error, so I'm assuming the namespace is the problem)

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

the RateWebServicesSchema.xsd, seems to tell anything interpreting it to use the rate namespace for the sub-element in the 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>
 [.....]

As mentioned, the envelope created by php defines common as ns1 and rate as ns2, but when I run it through __soapCall and get the 'Pickup Type Code missing' and look at the request, I see:

<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>      [......]

Request is in 'common' and so it's being properly shown as ns1, but the code/description is for some reason getting pointed over to ns1.

One weird thing I haven't been able to trace back was that it at one point previously was assigning them correctly and I'm not sure what would/could have changed to make it start pointing toward common(ns1) instead of rate(ns2) namespace.

So this generates a couple of questions.

First (and most important) is anyone aware of why php might be assigning the incorrect namespace and/or how I can 'instruct' SoapClient to use a specific one for redundantly named data structures?

Second, to make it easier for debugging and out of curiosity, is there anyway to pre-define the keys for those namespaces so I'm not constantly having to translate ns1 vs common or ns2 vs rate, etc.?

Third, I used WSDLInterpreter v1.0 to generate the various php based object representations of the schema. It wasn't 100%, so, for example it didn't build some of the 'common' namespace objects and I had to build those by hand for common:Request and common:Response for example. Obviously, I could not create more than one object in the same directory for CodeDescriptionType. Is there any way to use php [such as php namespaces?] to help differentiate what soap uses and what soap calls them? Maybe a phpdoc tag or something? e.g. create more than one CodeDescription type by separating the php classes in directories specific to the xml namespaces. (just widely speculating here)

UPDATE: I found in another post that you can specify the namespace(s) if you create the outgoing Soap data using SoapVar, so I changed my code to build each sub-branch of the outgoing data by wrapping them when a given branch is added with a SoapVar specifying the namespace relevant to that branch. While this seems to be working somewhat, it does it in a weird fashion somewhat inconsistently. Some elements are properly named as namespace:type while others are named namespace:type xsi:type="namespace:type" redundantly.

For example, the code above now has the proper namespaces but shows up like:

<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条回答 默认 最新

  • dongqie2355 2018-08-08 16:35
    关注

    I was having the same problem (though currently working in the TNTWS service, not RateWS - will be getting to that one shortly). I was getting the same error, with PHP assigning an incorrect namespace to something that looked like it should be correct.

    I have generated PHP classes from the WSDL files into their own namespaces (UPS\TNTWS, UPS\RateWS, etc).

    This was the code that was failing with the same issue you were experiencing:

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

    Which produced:

    <?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>
    

    And this is what succeeds:

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

    producing:

    <?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>
    

    Apparently UOMCodeDescriptionType is distinct from CodeDescriptionType, and using the wrong one breaks things.

    评论

报告相同问题?

悬赏问题

  • ¥15 MATLAB怎么通过柱坐标变换画开口是圆形的旋转抛物面?
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥30 用arduino开发esp32控制ps2手柄一直报错
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题
  • ¥15 Visual Studio问题