Skip to content

XML Web Services — SOAP & REST with XML

DodaTech Updated 2026-06-20 9 min read

In this tutorial, you'll learn about XML Web Services. We cover key concepts, practical examples, and best practices.

XML web services use structured XML messages for systems communication — with SOAP providing a formal protocol and REST offering resource-based APIs.

What You'll Learn

  • The SOAP protocol envelope, header, body, and fault structures
  • How WSDL defines service contracts, operations, and message types
  • Building REST APIs that consume and produce XML payloads
  • Security considerations including XML signing, encryption, and WS-Security

Why It Matters

Enterprise systems — banking, healthcare (HL7), government, insurance — rely on XML web services for transactional reliability, schema enforcement, and cross-platform interoperability. Every major security tool, including Durga Antivirus Pro, uses XML-based APIs for threat intelligence feeds and centralized management consoles.

Learning Path

flowchart LR
  A[XML Basics] --> B[XML vs JSON vs YAML]
  B --> C[RSS & Atom Feeds]
  C --> D[XML Configuration Files]
  D --> E[XML Web Services
You are here]

SOAP — Simple Object Access Protocol

SOAP is a messaging protocol that defines a strict XML structure for exchanging structured data. Think of SOAP as a standardized envelope: every message has the same format regardless of what's inside, making it predictable and reliable.

SOAP Message Structure

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <soap:Header>
    <auth:Authentication xmlns:auth="http://durga-antivirus.com/auth">
      <auth:ApiKey>abc123-def456-ghi789</auth:ApiKey>
      <auth:Timestamp>2026-06-20T10:30:00Z</auth:Timestamp>
      <auth:Signature>base64signature==</auth:Signature>
    </auth:Authentication>
  </soap:Header>

  <soap:Body>
    <tns:ScanFile xmlns:tns="http://durga-antivirus.com/scan">
      <tns:FileName>suspicious.doc</tns:FileName>
      <tns:FileContent>base64encodedcontent==</tns:FileContent>
      <tns:ScanOptions>
        <tns:HeuristicLevel>high</tns:HeuristicLevel>
        <tns:CheckArchives>true</tns:CheckArchives>
      </tns:ScanOptions>
    </tns:ScanFile>
  </soap:Body>

</soap:Envelope>

SOAP Envelope Components

Component Required Description
<Envelope> Yes Root element that wraps the entire message
<Header> No Metadata: authentication, routing, transaction context
<Body> Yes The actual request or response data
<Fault> Conditional Error information (appears in place of Body on failure)

SOAP Fault Response

When a SOAP service encounters an error, it returns a <Fault> element inside the Body:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <soap:Fault>
      <faultcode>soap:Server</faultcode>
      <faultstring>File scan failed</faultstring>
      <faultactor>https://scan.durga-antivirus.com/soap</faultactor>
      <detail>
        <tns:ScanFault xmlns:tns="http://durga-antivirus.com/scan">
          <tns:ErrorCode>SCAN-1004</tns:ErrorCode>
          <tns:ErrorMessage>File exceeds maximum scan size of 100MB</tns:ErrorMessage>
          <tns:FileSize unit="MB">150</tns:FileSize>
        </tns:ScanFault>
      </detail>
    </soap:Fault>
  </soap:Body>
</soap:Envelope>
Fault Element Description
<faultcode> Machine-readable error type (soap:VersionMismatch, soap:MustUnderstand, soap:Client, soap:Server)
<faultstring> Human-readable error description
<faultactor> URI identifying the source of the fault
<detail> Application-specific error details

WSDL — Web Services Description Language

WSDL is an XML document that describes a web service's interface — what operations it offers, what messages it expects, and how to communicate with it. Think of WSDL as a restaurant menu: it tells you what dishes are available, what ingredients they contain, and how to order them.

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="ScanService"
    targetNamespace="http://durga-antivirus.com/scan"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://durga-antivirus.com/scan"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <!-- Data types used in messages -->
  <types>
    <xsd:schema targetNamespace="http://durga-antivirus.com/scan">
      <xsd:element name="ScanFileRequest">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="FileName" type="xsd:string"/>
            <xsd:element name="FileContent" type="xsd:base64Binary"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="ScanFileResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="ThreatFound" type="xsd:boolean"/>
            <xsd:element name="ThreatName" type="xsd:string" minOccurs="0"/>
            <xsd:element name="Severity" type="xsd:string" minOccurs="0"/>
            <xsd:element name="ScanDuration" type="xsd:double"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
  </types>

  <!-- Abstract messages -->
  <message name="ScanFileRequestMessage">
    <part name="parameters" element="tns:ScanFileRequest"/>
  </message>
  <message name="ScanFileResponseMessage">
    <part name="parameters" element="tns:ScanFileResponse"/>
  </message>

  <!-- Port type (abstract interface) -->
  <portType name="ScanPortType">
    <operation name="ScanFile">
      <input message="tns:ScanFileRequestMessage"/>
      <output message="tns:ScanFileResponseMessage"/>
      <fault name="ScanFault" message="tns:ScanFaultMessage"/>
    </operation>
  </portType>

  <!-- Binding (protocol + data format) -->
  <binding name="ScanBinding" type="tns:ScanPortType">
    <soap:binding style="document"
                  transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="ScanFile">
      <soap:operation soapAction="http://durga-antivirus.com/scan/ScanFile"/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
      <fault>
        <soap:fault name="ScanFault" use="literal"/>
      </fault>
    </operation>
  </binding>

  <!-- Service endpoint -->
  <service name="ScanService">
    <port name="ScanPort" binding="tns:ScanBinding">
      <soap:address location="https://scan.durga-antivirus.com/soap/scan"/>
    </port>
  </service>
</definitions>

WSDL Structure Layers

Section Purpose
<types> Defines data types (usually XSD) used in messages
<message> Abstract definition of input/output/fault messages
<portType> Abstract interface — groups operations
<binding> Concrete protocol and data format binding
<service> Physical endpoint URL where the service lives

REST with XML

While REST APIs commonly use JSON, many enterprise APIs still use XML. REST with XML uses HTTP methods (GET, POST, PUT, DELETE) with XML request and response bodies.

import requests
import xml.etree.ElementTree as ET

# REST API endpoint that accepts XML
url = "https://api.durga-antivirus.com/v1/threats"

# Build XML request body
threat_report = ET.Element("ThreatReport")
threat_report.set("xmlns", "http://durga-antivirus.com/threats")

header = ET.SubElement(threat_report, "Header")
ET.SubElement(header, "Source").text = "endpoint-01"
ET.SubElement(header, "Timestamp").text = "2026-06-20T10:30:00Z"
ET.SubElement(header, "ApiKey").text = "abc123-def456"

threats = ET.SubElement(threat_report, "Threats")

threat1 = ET.SubElement(threats, "Threat",
                         type="malware", severity="critical")
ET.SubElement(threat1, "Name").text = "Trojan.Generic.12345"
ET.SubElement(threat1, "FilePath").text = "C:\\Users\\user\\invoice.exe"
ET.SubElement(threat1, "MD5").text = "d41d8cd98f00b204e9800998ecf8427e"
ET.SubElement(threat1, "Action").text = "quarantined"

xml_body = ET.tostring(threat_report, encoding="unicode")

# POST XML to the API
headers = {"Content-Type": "application/xml"}
response = requests.post(url, data=xml_body, headers=headers)

# Parse XML response
response_root = ET.fromstring(response.text)
status = response_root.find(".//{http://durga-antivirus.com/threats}Status")
print(f"Response status: {status.text}")

Expected output:

Response status: ACCEPTED

Building an XML REST Endpoint with Flask

from flask import Flask, request, Response
import xml.etree.ElementTree as ET

app = Flask(__name__)

@app.route("/api/v1/scan", methods=["POST"])
def scan_file():
    content_type = request.headers.get("Content-Type", "")

    if "application/xml" not in content_type:
        return Response(
            "<error>Content-Type must be application/xml</error>",
            status=415,
            mimetype="application/xml"
        )

    try:
        root = ET.fromstring(request.data)
        ns = {"tns": "http://durga-antivirus.com/scan"}

        file_name = root.find("tns:FileName", ns).text
        options = root.find("tns:ScanOptions", ns)

        # Simulate scan
        heuristic = options.find("tns:HeuristicLevel", ns).text

        # Build XML response
        response = ET.Element("ScanResponse")
        ET.SubElement(response, "ThreatFound").text = "false"
        ET.SubElement(response, "ThreatName")
        ET.SubElement(response, "Severity").text = "none"
        ET.SubElement(response, "ScanDuration").text = "1.234"

        xml_response = ET.tostring(response, encoding="unicode")
        return Response(xml_response, mimetype="application/xml")

    except ET.ParseError as e:
        return Response(
            f"<error>Invalid XML: {str(e)}</error>",
            status=400,
            mimetype="application/xml"
        )

if __name__ == "__main__":
    app.run(port=5000, debug=True)

Test the endpoint:

curl -X POST http://localhost:5000/api/v1/scan \
  -H "Content-Type: application/xml" \
  -d '<?xml version="1.0"?>
<ScanRequest xmlns="http://durga-antivirus.com/scan">
  <FileName>test.doc</FileName>
  <ScanOptions>
    <HeuristicLevel>high</HeuristicLevel>
  </ScanOptions>
</ScanRequest>'

Expected output:

<?xml version="1.0" encoding="UTF-8"?>
<ScanResponse>
  <ThreatFound>false</ThreatFound>
  <ThreatName/>
  <Severity>none</Severity>
  <ScanDuration>1.234</ScanDuration>
</ScanResponse>

SOAP Client Example in Python

import requests

# SOAP 1.1 request template
soap_request = """<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:scan="http://durga-antivirus.com/scan">
  <soap:Header>
    <scan:ApiKey>abc123-def456</scan:ApiKey>
  </soap:Header>
  <soap:Body>
    <scan:ScanFile>
      <scan:FileName>suspicious.doc</scan:FileName>
      <scan:FileContent>{base64_content}</scan:FileContent>
    </scan:ScanFile>
  </soap:Body>
</soap:Envelope>"""

# Send SOAP request
headers = {
    "Content-Type": "text/xml; charset=utf-8",
    "SOAPAction": "http://durga-antivirus.com/scan/ScanFile"
}

response = requests.post(
    "https://scan.durga-antivirus.com/soap/scan",
    data=soap_request,
    headers=headers
)

print(response.text)

Expected output:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <scan:ScanFileResponse xmlns:scan="http://durga-antivirus.com/scan">
      <scan:ThreatFound>true</scan:ThreatFound>
      <scan:ThreatName>Trojan.Generic.12345</scan:ThreatName>
      <scan:Severity>critical</scan:Severity>
      <scan:ScanDuration>2.345</scan:ScanDuration>
    </scan:ScanFileResponse>
  </soap:Body>
</soap:Envelope>

WS-Security

WS-Security (WSS) is an extension that adds security to SOAP messages — signing, encryption, and tokens:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
               xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <soap:Header>
    <wsse:Security>
      <wsse:UsernameToken wsu:Id="UsernameToken-1">
        <wsse:Username>admin</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">
          base64digest=
        </wsse:Password>
        <wsse:Nonce>base64nonce=</wsse:Nonce>
        <wsu:Created>2026-06-20T10:30:00Z</wsu:Created>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>
  <soap:Body wsu:Id="Body-1">
    <tns:GetThreatIntel xmlns:tns="http://durga-antivirus.com/intel">
      <tns:ThreatHash>d41d8cd98f00b204e9800998ecf8427e</tns:ThreatHash>
    </tns:GetThreatIntel>
  </soap:Body>
</soap:Envelope>

SOAP vs REST with XML

Aspect SOAP REST with XML
Protocol Formal, rigid Architectural style
Transport HTTP, SMTP, JMS HTTP only
State Stateless or stateful Stateless
Caching Not supported Built-in (HTTP caching)
Security WS-Security (built-in) HTTPS + tokens (external)
Transaction support Built-in (WS-AtomicTransaction) Manual
Discovery WSDL (self-describing) Documentation or OpenAPI
Error handling SOAP Fault (standardized) HTTP status codes
Performance Slower (XML parsing overhead) Faster
Tooling Extensive (code generation) Minimal (plain HTTP)

Common Mistakes

1. Missing SOAPAction header

SOAP 1.1 requires the SOAPAction HTTP header. Without it, many servers reject the request.

2. Forgetting namespace prefixes

<!-- WRONG: missing namespace prefix in Body -->
<Body>
  <ScanFile>...</ScanFile>
</Body>
<!-- CORRECT -->
<soap:Body>
  <scan:ScanFile>...</scan:ScanFile>
</soap:Body>

3. Improper XML escaping in payloads

Binary data like file contents must be base64-encoded inside XML, not included raw.

4. Not validating WSDL before code generation

Invalid WSDL produces broken client stubs. Always validate WSDL with tools like xmllint.

5. Hardcoding endpoint URLs

# WRONG
url = "http://localhost:8080/soap"
# RIGHT
url = os.getenv("SOAP_ENDPOINT", "http://localhost:8080/soap")

6. XML parser vulnerabilities

XXE and XML bomb attacks are especially dangerous in web services because parsers process untrusted data from the network.

7. Content-Type mismatch

Sending XML to an endpoint expecting JSON (or vice versa) returns HTTP 415 Unsupported Media Type.

Practice Questions

  1. What is the purpose of WSDL in SOAP web services? WSDL is a machine-readable contract that describes available operations, input/output messages, data types, and endpoint URLs — enabling automatic client code generation.

  2. What is the difference between SOAP and REST? SOAP is a formal protocol with built-in security, transactions, and reliability — rigid but standardized. REST is an architectural style using plain HTTP — simpler, faster, and more flexible.

  3. What does a SOAP Fault element contain? <faultcode> (error type), <faultstring> (description), <faultactor> (source), and <detail> (app-specific error data).

  4. How do you secure a SOAP web service? Use WS-Security for message-level signing and encryption, HTTPS for transport security, API keys or tokens for authentication, and input validation against XSD schemas.

  5. When would you choose SOAP over REST? When you need built-in transaction support, formal contracts (WSDL), enterprise-grade security (WS-Security), or reliable messaging (WS-ReliableMessaging) — common in finance, healthcare, and government.

Challenge: Build a SOAP-based threat intelligence service that accepts a file hash, queries a signature database, and returns threat metadata (name, severity, category, first seen date) in a structured SOAP response with proper fault handling.

Real-world task: Durga Antivirus Pro needs a centralized management API. Design a RESTful XML API that allows administrators to list, create, update, and delete scan policies. Each policy includes name, scan paths, exclusion patterns, heuristic level, and schedule. Implement the GET and POST endpoints with XML request/response handling.

FAQ

What is the difference between SOAP and REST?

SOAP is a protocol with strict standards (WSDL, WS-Security, envelope format). REST is an architectural style using HTTP methods and resource URIs. SOAP is heavier but more standardized; REST is lighter but less formal.

Does REST require JSON?

No. REST can use any representation format — XML, JSON, YAML, or even plain text. The Content-Type header determines the format. Many enterprise REST APIs still use XML.

What is WSDL used for?

WSDL (Web Services Description Language) defines the contract of a SOAP service — what operations it provides, what data types it uses, and where it's located. Client tools can generate code directly from WSDL.

What's Next

Tutorial What You'll Learn
XML Digital Signatures Sign and verify XML documents for security
XSLT Explained — Transform XML into HTML Transform XML responses into readable formats
XPath Explained — Querying XML Navigate XML documents to extract specific data

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-20.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro