I know this question is old, but I just had this same issue as I was accessing a third-party SOAP API with a WSDL that pointed to the wrong endpoint (the third party told me the correct endpoint but hadn't updated their WSDL). The accepted answer did point me in the right direction, but I'd like to offer some additional details that weren't immediately apparent to a fairly novice developer such as myself.
Start by noticing that Zeep's documentation shows that the method zeep.Client.create_service() has two parameters.
binding_name – The QName of the binding
address – The address of the endpoint
Figuring out the binding_name
Option 1 - Read through the WSDL
The binding_name comes from the attribute binding
in the WSDL. The issue is that the value of that attribute usually includes a reference to a name elsewhere in the WSDL that you have to manually resolve before using it to create a custom service.
In the case of the excerpt from the OP's WSDL (slightly formatted and ***emphasis added
***)...
<service name="DeviceConfigurationService">
<port name="DeviceConfigurationPort" ***binding="xrx:DeviceConfigurationBinding"***>
<soap:address location="http://localhost/webservices/office/device_configuration/1"/>
</port>
</service>
... the value of binding
is "xrx:DeviceConfigurationBinding"
.
While this is the binding_name
used by Zeep, you can't just copy and paste it into the parameter of create_service()
because it is partially comprised of xrx
- a name defined locally within the WSDL. Zeep automatically resolves the value of this kind of name when it originally parses the WSDL, so when you tell Zeep to point an existing binding to a different endpoint you have to resolve the binding name yourself so Zeep knows which binding you are talking about (that's why @jeffgabhart used {https://path-to-xrx-namespace}
in his answer). In the end you should end up with complete binding_name
of the format {NAMESPACE}BINDING
.
Note that xrx
isn't the only possible name. For me, the name was tns
and for you it may be something different. Whatever it is, you should be able to find the definition of that name somewhere in the WSDL.
Option 2 - Use Zeep's WSDL parsing utility
Another option is the one suggested by @576i. Running the command python -mzeep WSDL_URL
will spit out the information Zeep gathers from the given WSDL. One heading should say "Bindings" followed by a list (possibly of length 1) of binding_name
's. From there you can copy the one you need to change the endpoint for.
Option 3 - Get it from the Zeep Client object
This one feels more like a hack, but list(zeep_client.wsdl.port_types)
gives a list of all binding names that Zeep found in the WSDL used to create the zeep_client
.
Figuring out the address
Lastly, for the sake of completeness, the address
is simply the new endpoint you want to use instead of the one defined in the WSDL.
I hope this helps smooth out the learning curve for someone!