0
votes

I'm sending requests to an (internal) soap service. I'm currently testing the SUDS (Jurko's fork) and OSA python soap libraries. Both are unable to marshal the response.

The raw xml response to a successful request is:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Body>
    <ns2:geocodeAddressResponse xmlns:ns2="http://geocodegateway">
      <geocodedAddress>
        <streetLine>1 SOME STREET</streetLine>
        <suburb>SOMEBURB</suburb>
        <state>SS</state>
        <postcode>1234</postcode>
        <x>111.222222</x>
        <y>-22.333333</y>
      </geocodedAddress>       
etc...

Both the OSA and SUDS libs raise exceptions:

  • The OSA exception is ValueError: 'streetLine' is not in list.
  • The SUDS exception is TypeNotFound: Type not found: 'streetLine'

The XSD (imported by the WSDL) for the soap service is:

<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.7-b01-. --><xs:schema xmlns:gns="http://geocodegateway" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://geocodegateway">
  <xs:element name="address" nillable="true" type="gns:address"></xs:element>
  <xs:element name="geocodeAddressRequest" nillable="true" type="gns:geocodeAddressRequest"></xs:element>
  <xs:element name="geocodeAddressResponse" nillable="true" type="gns:geocodeAddressResponse"></xs:element>
  <xs:complexType name="address">
    <xs:sequence>
      <xs:element name="streetLine" type="xs:string"></xs:element>
      <xs:element name="suburb" type="xs:string"></xs:element>
      <xs:element name="state" type="xs:string"></xs:element>
      <xs:element name="postcode" type="xs:string"></xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="geocodeAddressRequest">
    <xs:sequence>
      <xs:element name="appId" type="xs:string"></xs:element>
      <xs:element name="address" nillable="true" type="gns:address"></xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="geocodeAddressResponse">
    <xs:sequence>
      <xs:element name="responseCode" type="xs:string" maxOccurs="1" minOccurs="1"></xs:element>
      <xs:element name="geocodedAddress">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="address" nillable="true" type="gns:address"></xs:element>
            <xs:element name="x" type="xs:string"></xs:element>
            <xs:element name="y" type="xs:string"></xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

If I modify the response XML via a SUDS MessagePlugin hook to wrap the streetLine, suburb, etc... elements in an address element, then SUDS marshals the response correctly.

Alternatively, if I modify the XSD using a suds DocumentPlugin hook (as per below) to remove the address type and include separate streetLine, suburb, etc... elements , then SUDS marshals the response correctly.

<xs:complexType name="geocodeAddressResponse">
  <xs:sequence>
    <xs:element name="responseCode" type="xs:string" maxOccurs="1" minOccurs="1"/>
    <xs:element name="geocodedAddress">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="streetLine" type="xs:string"></xs:element>
          <xs:element name="suburb" type="xs:string"></xs:element>
          <xs:element name="state" type="xs:string"></xs:element>
          <xs:element name="postcode" type="xs:string"></xs:element>
          <xs:element name="x" type="xs:string"></xs:element>
          <xs:element name="y" type="xs:string"></xs:element>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
  </xs:sequence>
</xs:complexType>

I suggested to the developer of the soap service that perhaps the XSD or the XML response should be modified so they are consistent but was advised that they seemed to be correct and to check if the python soap library I'm using is specifying/interpreting document/literal vs document/literal wrapped correctly (which I'm not sure how that applies here).

Question: Is the SOAP response consistent with the WSDL/XSD and the python soap libraries not interpreting it correctly (or me not using them correctly)?

2

2 Answers

1
votes

The raw XML response is not inline with the WSDL.

Maybe there is a confusion between type and element:

This part of the XSD bundled in the WSDL defines a type named "address":

 <xs:complexType name="address">
    <xs:sequence>
        <xs:element name="streetLine" type="xs:string"></xs:element>
        <xs:element name="suburb" type="xs:string"></xs:element>
        <xs:element name="state" type="xs:string"></xs:element>
        <xs:element name="postcode" type="xs:string"></xs:element>
   </xs:sequence>
 </xs:complexType>

whereas this part of the same XSD defines an element which is also called "address" inside geocodedAddress and is of the type "address" defined above:

 <xs:element name="geocodedAddress">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="address" nillable="true" type="gns:address"></xs:element>

So according to that definition the raw soap response should look like this:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Body>
    <ns2:geocodeAddressResponse xmlns:ns2="http://geocodegateway">
      <geocodedAddress>
        <address>
            <streetLine>1 SOME STREET</streetLine>
            <suburb>SOMEBURB</suburb>
            <state>SS</state>
            <postcode>1234</postcode>
            <x>111.222222</x>
            <y>-22.333333</y>
        </address>
      </geocodedAddress>  

And the equivalent of the geocodedAddress written without the separate gns:address type definition would be something like this:

<xs:complexType name="geocodeAddressResponse">
  <xs:sequence>
    <xs:element name="responseCode" type="xs:string" maxOccurs="1" minOccurs="1"/>
    <xs:element name="geocodedAddress">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="address">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="streetLine" type="xs:string"></xs:element>
                <xs:element name="suburb" type="xs:string"></xs:element>
                <xs:element name="state" type="xs:string"></xs:element>
                <xs:element name="postcode" type="xs:string"></xs:element>
                <xs:element name="x" type="xs:string"></xs:element>
                <xs:element name="y" type="xs:string"></xs:element>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
  </xs:sequence>
</xs:complexType>
1
votes

You are right, this is not consistent.

Option 1

If the XSD looks like this:

  <xs:element name="geocodedAddress">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="address" nillable="true" type="gns:address"></xs:element>
        <xs:element name="x" type="xs:string"></xs:element>
        <xs:element name="y" type="xs:string"></xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

the XML should look like this:

  <geocodedAddress>
     <address>
        <streetLine>Street 1</streetLine>
        <suburb>Suburb 1</suburb>
        <state>XX</state>
        <postcode>1234</postcode>
     </address>
     <x>111.11</x>
     <y>-22.22</y>
  </geocodedAddress>

Option 2

If the XSD looks like this:

<xs:element name="geocodedAddress">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="streetLine" type="xs:string"></xs:element>
      <xs:element name="suburb" type="xs:string"></xs:element>
      <xs:element name="state" type="xs:string"></xs:element>
      <xs:element name="postcode" type="xs:string"></xs:element>
      <xs:element name="x" type="xs:string"></xs:element>
      <xs:element name="y" type="xs:string"></xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:element>

the XML should look like this:

  <geocodedAddress>
      <streetLine>Street 1</streetLine>
      <suburb>Suburb 1</suburb>
      <state>XX</state>
      <postcode>1234</postcode>
      <x>111.11</x>
      <y>-22.22</y>
  </geocodedAddress>