title: SOAP Response Schema Validation
body: <h2><strong>Short version:</strong></h2>
  
  <p>I'm trying to write an XSD that will validate my SOAP service's responses.  I feel compelled to just import http:// schemas.xmlsoap.org/soap/envelope/ instead of redefining the SOAP elements like Envelope, Head, and Body, but that xmlsoap.org schema definition of Body is too broad for my use--as soon as I import the SOAP Schema, suddenly my XSD (that I've carefully tailored to my service) validates <em>all</em> SOAP messages.  </p>
  
  <p><strong>How should I handle the definition of the SOAP envelope, head, body in my XSD?</strong></p>
  
  <p>I suspect the problem is that I'm trying to re-use other schemas that I shouldn't be trying to re-use.  Certainly, those Schemas for SOAP are intended to define what (all) SOAP messages should look like.  And maybe I just need to define in my schema what I want my particular soap body to look like.</p>
  
  <p>I might have just answered my own question.  Maybe someone has a different solution?  </p>
  
  <h2><strong>Long version:</strong></h2>
  
  <p>I'm having a little trouble authoring an XSD to describe the response message from one of my SOAP services.</p>
  
  <p>Here's an example response from my service that I'm trying to validate:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;
     &lt;soap:Body&gt;
        &lt;helloResponse xmlns="http://justinfaulkner/wsdl/1.0"&gt;
           &lt;Message&gt;Hello, Justin!&lt;/Message&gt;
           &lt;Message&gt;Your lucky numbers are: 329, 9&lt;/Message&gt;
        &lt;/helloResponse&gt;
     &lt;/soap:Body&gt;
  &lt;/soap:Envelope&gt;
  </code></pre>
  
  <p>My goal is to validate responses from my service with an XSD.
  So, I hand-authored an XSD that describes all the types that belong in my service's soap:Body</p>
  
  <pre><code>&lt;?xml version="1.0"?&gt;
  &lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://justinfaulkner/wsdl/1.0" xmlns:tns="http://justinfaulkner/wsdl/1.0"&gt;
     &lt;xsd:complexType name="helloResponseType"&gt;
        &lt;xsd:sequence&gt;
           &lt;xsd:element name="Message" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/&gt;
        &lt;/xsd:sequence&gt;
     &lt;/xsd:complexType&gt;
     &lt;xsd:element name="helloResponse" type="tns:helloResponseType"/&gt;
  &lt;/xsd:schema&gt;
  </code></pre>
  
  <p>When I tried to validate the example response (first XML snippet) with the Schema (2nd snippet) using PHP's DOMDocument::schemaValidateSource() functionality, the validator pointed out my first obvious mistake:</p>
  
  <blockquote>
    <p>Element 'soap:Envelope': No matching global declaration available</p>
  </blockquote>
  
  <p>"Oops, duh," I thought,  "Those elements are defined in SOAP's namespace, so I need to import SOAP's XSD."</p>
  
  <p>So I edited my XSD and added an import:</p>
  
  <pre><code>&lt;xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/&gt;
  </code></pre>
  
  <p>And it worked!  DOMDocument::schemaValidateSource returns true when I validate the soap response with the XSD.</p>
  
  <p><strong>Then, as a sanity check</strong>, I took a different soap response XSD I had lying around:</p>
  
  <pre><code>&lt;?xml version="1.0"?&gt;
  &lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://justinfaulkner/wsdl/1.0" xmlns:tns="http://justinfaulkner/wsdl/1.0"&gt;
     &lt;xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/&gt;
     &lt;xsd:complexType name="OtherServiceResponseType"&gt;
        &lt;xsd:all&gt;
           &lt;xsd:element name="CompletionCode" type="xsd:string"/&gt;
           &lt;xsd:element name="ResponseMessage" type="xsd:string"/&gt;
        &lt;/xsd:all&gt;
     &lt;/xsd:complexType&gt;
     &lt;xsd:element name="OtherServiceResponse" type="tns:OtherServiceResponseType"/&gt;
  &lt;/xsd:schema&gt;
  </code></pre>
  
  <p>And I tried to validate my soap response with this completely unrelated Schema...</p>
  
  <p>And the schema that, at first glance, doesn't describe this message at all, <strong>also validates the soap response.</strong></p>
  
  <p>Then I realize that XSD's Schema must be the reason the response is validating against these two different schemas.  The SOAP schema I'm importing from <a href="http://schemas.xmlsoap.org/soap/envelope/" rel="noreferrer">http://schemas.xmlsoap.org/soap/envelope/</a> defines the Body element to be:</p>
  
  <pre><code>&lt;xs:element name="Body" type="tns:Body" /&gt;
  &lt;xs:complexType name="Body" &gt;
  &lt;xs:sequence&gt;
    &lt;xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" /&gt;
  &lt;/xs:sequence&gt;
  &lt;xs:anyAttribute namespace="##any" processContents="lax" &gt;
    &lt;xs:annotation&gt;
   &lt;xs:documentation&gt;
     Prose in the spec does not specify that attributes are allowed on the Body element
   &lt;/xs:documentation&gt;
    &lt;/xs:annotation&gt;
  &lt;/xs:anyAttribute&gt;
  &lt;/xs:complexType&gt;
  </code></pre>
  
  <p>Which allows the contents of the Body tag to be basically anything.</p>
  
  <p>That makes sense, the purpose of XSD's XSD is to define what ALL XSDs should look like, not just mine.  </p>
  
  <p><strong>So my question is, how <em>should</em> I build an XSD to validate these SOAP responses, reusing existing SOAP XSDs if possible?</strong></p>
  
  <p>Here's the direction I've been pursuing...</p>
  
  <ul>
  <li>I guess I could throw xmlsoap.org's XSD schema out the window and redefine Envelope and Body myself, specifying exactly what should show up in the Body element.  But I feel like I'll end up basically having a copy of all the soap elements inside my own XSD, with a slightly different Head and Body definition, and that feels like a violation of DRY.</li>
  <li>Is there a way I can import xmlsoap.org's XSD but then override the definition of soap:Body from inside my XSD?</li>
  </ul>