PHP SoapClient不处理WSDL中的abstract和substitutionGroup属性

时间:2022-03-27 11:01:34

I'm sending a call to Canada Post using their supplied wsdl which contains a section like this:

我正在使用他们提供的wsdl向Canada Post发送一个电话,其中包含以下部分:

<!-- group-id and transmit-shipment are mutually exclusive -->
<xsd:element name="groupIdOrTransmitShipment" abstract="true" />
<xsd:element name="group-id" type="tns:GroupIDType" substitutionGroup="tns:groupIdOrTransmitShipment"/>
<xsd:element name="transmit-shipment" type="xsd:boolean" fixed="true" substitutionGroup="tns:groupIdOrTransmitShipment"/>

<xsd:complexType name="ShipmentType">
    <xsd:all>
        <xsd:element ref="tns:groupIdOrTransmitShipment" />
        <xsd:element name="quickship-label-requested" type="xsd:boolean" minOccurs="0"/>
        <xsd:element name="cpc-pickup-indicator" type="xsd:boolean" fixed="true" minOccurs="0"/>
        <xsd:element name="requested-shipping-point" type="tns:PostalCodeType" minOccurs="0"/>
        <xsd:element name="shipping-point-id" type="tns:OutletIDType" minOccurs="0" />
        <xsd:element name="expected-mailing-date" type="xsd:date" minOccurs="0"/>
        <xsd:element name="delivery-spec" type="tns:DeliverySpecType"/>
        <xsd:element name="return-spec" type="tns:ReturnSpecType" minOccurs="0"/>
    </xsd:all>
</xsd:complexType>

In their code sample they extend the Soap class and override the __doRequest() Soap method like this:

在他们的代码示例中,他们扩展了Soap类并覆盖了__doRequest()Soap方法,如下所示:

/*
 Need to override SoapClient because the abstract element 'groupIdOrTransmitShipment' is expected to be in the request in order for validation to pass.
So, we give it what it expects, but in __doRequest we modify the request by removing the abstract element and add the correct element.

*/

class MySoapClient extends SoapClient {

    function __construct($wsdl, $options = null) {
        parent::__construct($wsdl, $options);
    }

    function __doRequest($request, $location, $action, $version, $one_way = NULL) {
        $dom = new DOMDocument('1.0');
        $dom->loadXML($request);
        //get element name and values of group-id or transmit-shipment.
        $groupIdOrTransmitShipment =  $dom->getElementsByTagName("groupIdOrTransmitShipment")->item(0);
        $element = $groupIdOrTransmitShipment->firstChild->firstChild->nodeValue;
        $value = $groupIdOrTransmitShipment->firstChild->firstChild->nextSibling->firstChild->nodeValue;

        //remove bad element
        $newDom = $groupIdOrTransmitShipment->parentNode->removeChild($groupIdOrTransmitShipment);

        //append correct element with namespace
        $body =  $dom->getElementsByTagName("shipment")->item(0);
        $newElement = $dom->createElement($element, $value);
        $body->appendChild($newElement);

        //save $dom to string
        $request = $dom->saveXML();
        //echo $request;

        //doRequest
        return parent::__doRequest($request, $location, $action, $version);
    }
}

Using their overidden method works fine as it alters the xml request but it's utterly confusing to me why they are doing this. Is there something fundamentally wrong with the WSDL? Is this a bug in PHP's SoapClient? I'd like a way to send a valid request without overriding any core class methods.

使用他们的overover方法可以正常工作,因为它改变了xml请求,但是为什么他们这样做会让我感到非常困惑。 WSDL是否存在根本性的错误?这是PHP的SoapClient中的错误吗?我想要一种发送有效请求而不覆盖任何核心类方法的方法。

According to my understanding, the author wants either a group-id or transmit-shipment element but not both or none. Since you can't have a <choice> element inside an <all> element, according to this discussion on w3c.org, it should be fine to declare a substitution group for this purpose and include only one of the two elements in my request, but if I only include transmit-shipment and omit the abstract element groupIdOrTransmitShipment php returns a fault:

根据我的理解,作者想要一个group-id或transmit-shipment元素,但不是两个都没有。由于在 元素中不能有 元素,根据w3c.org上的讨论,为此目的声明一个替换组应该没问题,并且在我的请求中只包含两个元素中的一个,但如果我只包含传输 - 发货并省略抽象元素groupIdOrTransmitShipment php返回错误:

SOAP-ERROR: Encoding: object has no 'groupIdOrTransmitShipment' property

UPDATE: This is very old but could it be relevant? https://bugs.php.net/bug.php?id=48570

更新:这是非常古老但可能相关吗? https://bugs.php.net/bug.php?id=48570

1 个解决方案

#1


1  

I have had to overwrite and extend the php SoapClass also. It had to do with the php soapclass expecting a certain format in the request / response then what was being received/sent. Extending it allowed me to handle the formatting myself.

我不得不覆盖和扩展php SoapClass。它与php soapclass有关,期望请求/响应中的某种格式然后接收/发送的内容。扩展它允许我自己处理格式。

Nothing is wrong with the wsdl, the error is part of class. There is no way around the override

wsdl没有错,错误是类的一部分。覆盖无法绕过

#1


1  

I have had to overwrite and extend the php SoapClass also. It had to do with the php soapclass expecting a certain format in the request / response then what was being received/sent. Extending it allowed me to handle the formatting myself.

我不得不覆盖和扩展php SoapClass。它与php soapclass有关,期望请求/响应中的某种格式然后接收/发送的内容。扩展它允许我自己处理格式。

Nothing is wrong with the wsdl, the error is part of class. There is no way around the override

wsdl没有错,错误是类的一部分。覆盖无法绕过