ejemplo - PHP SoapClient no maneja los atributos abstract y substitutionGroup en WSDL
web service php soap ejemplo (1)
Tuve que sobrescribir y extender el phap SoapClass también. Tenía que ver con la clase de soap php esperando un determinado formato en la solicitud / respuesta y luego lo que se estaba recibiendo / enviando. La extensión me permitió manejar el formato yo mismo.
Nada está mal con el wsdl, el error es parte de la clase. No hay forma de evitar la anulación
Enviaré una llamada a Canada Post utilizando el archivo wsdl proporcionado que contiene una sección como esta:
<!-- 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>
En su ejemplo de código extienden la clase Soap y anulan el método Soap __doRequest()
esta manera:
/*
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);
}
}
Usar su método overidden funciona bien ya que altera la solicitud xml pero me resulta completamente confuso por qué lo están haciendo. ¿Hay algo fundamentalmente malo con el WSDL? ¿Es esto un error en SoapClient de PHP? Me gustaría una forma de enviar una solicitud válida sin anular ningún método de clase principal.
Según lo que yo entiendo, el autor quiere un elemento group-id
o transmit-shipment
pero no ambos o ninguno. Como no puede tener un elemento <choice>
dentro de un elemento <all>
, de acuerdo con esta discusión en w3c.org , debería estar bien declarar un grupo de sustitución para este propósito e incluir solo uno de los dos elementos en mi solicitud , pero si solo groupIdOrTransmitShipment
el transmit-shipment
y groupIdOrTransmitShipment
elemento abstracto groupIdOrTransmitShipment
php devuelve un error:
SOAP-ERROR: Encoding: object has no ''groupIdOrTransmitShipment'' property
ACTUALIZACIÓN: Esto es muy antiguo pero ¿podría ser relevante? https://bugs.php.net/bug.php?id=48570