views:

30

answers:

0

Short version:

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 all SOAP messages.

How should I handle the definition of the SOAP envelope, head, body in my XSD?

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.

I might have just answered my own question. Maybe someone has a different solution?

Long version:

I'm having a little trouble authoring an XSD to describe the response message from one of my SOAP services.

Here's an example response from my service that I'm trying to validate:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;
   <soap:Body>
      <helloResponse xmlns="http://justinfaulkner/wsdl/1.0"&gt;
         <Message>Hello, Justin!</Message>
         <Message>Your lucky numbers are: 329, 9</Message>
      </helloResponse>
   </soap:Body>
</soap:Envelope>

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

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://justinfaulkner/wsdl/1.0" xmlns:tns="http://justinfaulkner/wsdl/1.0"&gt;
   <xsd:complexType name="helloResponseType">
      <xsd:sequence>
         <xsd:element name="Message" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
   </xsd:complexType>
   <xsd:element name="helloResponse" type="tns:helloResponseType"/>
</xsd:schema>

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:

Element 'soap:Envelope': No matching global declaration available

"Oops, duh," I thought, "Those elements are defined in SOAP's namespace, so I need to import SOAP's XSD."

So I edited my XSD and added an import:

<xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/&gt;

And it worked! DOMDocument::schemaValidateSource returns true when I validate the soap response with the XSD.

Then, as a sanity check, I took a different soap response XSD I had lying around:

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://justinfaulkner/wsdl/1.0" xmlns:tns="http://justinfaulkner/wsdl/1.0"&gt;
   <xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/&gt;
   <xsd:complexType name="OtherServiceResponseType">
      <xsd:all>
         <xsd:element name="CompletionCode" type="xsd:string"/>
         <xsd:element name="ResponseMessage" type="xsd:string"/>
      </xsd:all>
   </xsd:complexType>
   <xsd:element name="OtherServiceResponse" type="tns:OtherServiceResponseType"/>
</xsd:schema>

And I tried to validate my soap response with this completely unrelated Schema...

And the schema that, at first glance, doesn't describe this message at all, also validates the soap response.

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 http://schemas.xmlsoap.org/soap/envelope/ defines the Body element to be:

<xs:element name="Body" type="tns:Body" />
<xs:complexType name="Body" >
<xs:sequence>
  <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
</xs:sequence>
<xs:anyAttribute namespace="##any" processContents="lax" >
  <xs:annotation>
 <xs:documentation>
   Prose in the spec does not specify that attributes are allowed on the Body element
 </xs:documentation>
  </xs:annotation>
</xs:anyAttribute>
</xs:complexType>

Which allows the contents of the Body tag to be basically anything.

That makes sense, the purpose of XSD's XSD is to define what ALL XSDs should look like, not just mine.

So my question is, how should I build an XSD to validate these SOAP responses, reusing existing SOAP XSDs if possible?

Here's the direction I've been pursuing...

  • 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.
  • Is there a way I can import xmlsoap.org's XSD but then override the definition of soap:Body from inside my XSD?