Part 2: WSDL and Service Contracts
Reading a WSDL for the First Time
The first time I opened a WSDL file, I closed it immediately. It was over 2,000 lines of nested XML with namespaces I had never seen. I did what most developers do: searched for a tool to generate code from it and moved on without understanding what was inside.
That approach worked until it didn't. When the generated client behaved unexpectedly — passing values in the wrong order, serialising optional fields incorrectly — I had no idea where to look. I had to go back and actually read the WSDL.
Understanding WSDL is a skill worth building. It is the formal contract between you and the service. When something goes wrong, the WSDL is where the answer is.
What is WSDL?
WSDL (Web Services Description Language) is an XML-based document that describes a SOAP web service. It answers:
What operations does the service offer?
What input does each operation expect?
What output does each operation return?
What data types are used?
Where is the service hosted (endpoint URL)?
What protocol does it use?
WSDL is to SOAP what OpenAPI (Swagger) is to REST — but with stricter enforcement. A well-written WSDL completely and unambiguously describes a service.
WSDL Structure
A WSDL document is made up of six major sections. Each builds on the previous.
Section 1: <types>
<types>This is where data types are defined using XSD (XML Schema Definition). It describes the structure of the XML elements that appear in requests and responses.
Key XSD primitives you will encounter repeatedly:
xsd:string
str
xsd:integer
int
xsd:decimal
Decimal
Do not use float for money
xsd:boolean
bool
Values are true / false (lowercase)
xsd:dateTime
datetime
ISO 8601 format
xsd:date
date
xsd:base64Binary
bytes
For file attachments
xsd:anyType
Any
Avoid: undefined structure
Section 2: <message>
<message>Messages define the input and output payloads for operations. Each message refers to elements defined in the <types> section.
The element attribute references an element defined in the <types> XSD. In Document/Literal style (the most common), each message has exactly one part with an element reference.
Section 3: <portType>
<portType>The portType is the abstract service interface — it lists operations without specifying how or where they run. Think of it as a Python abstract base class.
Operations can have:
inputonly — one-way operation (fire and forget)input+output— standard request-responseinput+output+fault— request-response with explicit error type
Section 4: <binding>
<binding>The binding maps the abstract portType to a concrete protocol (SOAP) and specifies the communication style and encoding.
Key fields to read:
style="document"— Document style (vsrpc)use="literal"— Literal encoding (vsencoded; always preferliteral)soapAction— TheSOAPActionHTTP header value (SOAP 1.1 only)
Section 5: <service>
<service>The service element specifies the actual network address where the service is deployed.
This is what zeep uses when you load a WSDL — it reads the location to know where to send requests.
Reading a Real WSDL with zeep
Once you understand the structure, you can use zeep to inspect any WSDL programmatically.
Output:
Inspecting Operation Signatures
Before calling any operation, I always check what the operation expects as input and what it returns.
For complex services, zeep also provides a helper to pretty-print the full type structure:
Writing a Minimal WSDL From Scratch
When building a SOAP service with spyne (covered in Part 3), the WSDL is generated automatically. But understanding how to write one manually helps when working with systems that require a handcrafted contract or when debugging generated WSDLs.
Here is a complete, minimal WSDL for a simple greeting service:
Save this as greeting.wsdl and load it with zeep to verify it is valid:
Common WSDL Patterns in the Wild
After working with several enterprise SOAP integrations, these are the patterns I encounter most frequently.
Fault Messages in portType
Most enterprise services declare explicit fault types. Always check if the portType operations have fault elements — they tell you what error types to handle.
Imported XSD Schemas
Large WSDLs often separate type definitions into external .xsd files and import them:
zeep handles imported schemas automatically. When loading WSDLs behind corporate firewalls, these imports can fail if the schema URLs are internal. In that case, download the schemas manually and update the schemaLocation to a local path.
Multiple Ports
A WSDL service can define multiple ports — often one for SOAP 1.1 and one for SOAP 1.2:
When using zeep, specify which port to use:
What's Next
You now understand:
The six sections of a WSDL document
How to read types, messages, portType, binding, and service
How to inspect a WSDL with zeep
How to write a minimal WSDL from scratch
Common patterns in enterprise WSDLs
In Part 3, we build a working SOAP service from scratch using spyne — defining operations, modelling complex types, and serving the endpoint over HTTP.
Last updated