dongzhidian3538 2015-12-10 20:50
浏览 54

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

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

<!-- 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:

/*
 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.

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:

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

  • 写回答

1条回答 默认 最新

  • dongliao1860 2015-12-21 15:43
    关注

    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.

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

    评论

报告相同问题?

悬赏问题

  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端
  • ¥15 基于PLC的三轴机械手程序
  • ¥15 多址通信方式的抗噪声性能和系统容量对比
  • ¥15 winform的chart曲线生成时有凸起
  • ¥15 msix packaging tool打包问题
  • ¥15 finalshell节点的搭建代码和那个端口代码教程
  • ¥15 Centos / PETSc / PETGEM