diff --git a/soap_server.module b/soap_server.module
index cd1b431..0b0dcf2 100644
--- a/soap_server.module
+++ b/soap_server.module
@@ -130,16 +130,19 @@ function soap_server_get_wsdl($endpoint) {
   if (is_array($wsdl_overrides) && !empty($wsdl_overrides)) {
     // if there is more than 1 wsdl the first takes priority allowing modules to override others by
     // setting system weight
-    $wsdl = array_shift($wsdl_overrides); 
+    $wsdl = array_shift($wsdl_overrides);
     return $wsdl;
   }
   $service_endpoint = url($endpoint->path, array('absolute' => TRUE));
   // get the content of the schema for each hose_xml profile using the standard namespace xs:
   $methods = _soap_server_get_methods($endpoint->name);
+  $types = '';
   foreach ($methods as $method_name => $method_config) {
-    // requests can specify which field to use to identify the node - default is nid
-    $parts = "";
-    // add parameters from the args array in the resource
+    $types .= "
+    <xsd:element name='{$method_name}'>
+      <xsd:complexType>
+        <xsd:sequence>";
+
     if (!empty($method_config['args'])) {
       foreach ((array)$method_config['args'] as $arg) {
         switch ($arg['type']) {
@@ -147,42 +150,54 @@ function soap_server_get_wsdl($endpoint) {
           case 'string':
           case 'struct':
           case 'array':
-            $parts .= "
-    <part name='"  . $arg['name'] ."' type='xsd:". $arg['type'] ."' />"; 
+            $types .= "<xsd:element name='{$arg['name']}' minOccurs='1' maxOccurs='1' type='xsd:{$arg['type']}'/>";
             break;
-          // we can work out how to deal with other parameter types later
           default:
-            $parts .= "
-    <part name='". $arg['name'] ."' type='xsd:any'/>";
-        }    
+            // we can work out how to deal with other parameter types later
+            $types .= "<xsd:element name='{$arg['name']}' minOccurs='1' maxOccurs='1' type='xsd:anyType'/>";
+        }
       }
     }
-    $requests .= "
-  <message name='". $method_name ."_request'>". $parts ."
+      $types .= "</xsd:sequence></xsd:complexType></xsd:element>";
+      $types .= "
+      <xsd:element name='{$method_name}_response'>
+        <xsd:complexType>
+        <xsd:sequence>
+        <xsd:element minOccurs='0' maxOccurs='1' name='{$method_name}_result'>
+        <xsd:complexType mixed='true'>
+        <xsd:sequence>
+        <xsd:any/>
+        </xsd:sequence>
+        </xsd:complexType>
+        </xsd:element>
+        </xsd:sequence>
+        </xsd:complexType>
+      </xsd:element>";
+      // requests can specify which field to use to identify the node - default is nid
+
+      // add parameters from the args array in the resource
+      $requests .= "<message name='{$method_name}_soap_in'>
+        <part name='parameters' element='tns:{$method_name}'/>
   </message>";
     // we don't know what the response will be so go for struct - seems like this is appropriate
     // for most resources
     $responses .= "
-  <message name='". $method_name ."_response'>
-    <part name='response_object' type='xsd:struct'/>
+  <message name='" . $method_name . "_soap_out'>
+      <part name='response_object' element='tns:{$method_name}_response'/>
   </message>";
     $port_type_operations .= "
   <operation name='$method_name'>
-    <input message='tns:". $method_name ."_request'/>
-    <output message='tns:". $method_name ."_response'/>
+    <input message='tns:" . $method_name . "_soap_in'/>
+    <output message='tns:" . $method_name . "_soap_out'/>
   </operation>";
     $binding_operations .= "
   <operation name='$method_name'>
-    <soap:operation soapAction='urn:xmethods-delayed-quotes#$method_name'/>
+    <soap:operation style='document' soapAction='urn:xmethods-delayed-quotes#$method_name'/>
     <input>
-      <soap:body 
-      	use='literal' 
-      	namespace='urn:xmethods-delayed-quotes' />
+      <soap:body use='literal'/>
     </input>
     <output>
-      <soap:body 
-      	use='literal' 
-      	namespace='urn:xmethods-delayed-quotes' />
+      <soap:body use='literal'/>
     </output>
   </operation>
 ";
@@ -209,7 +224,7 @@ function soap_server_wsdl_output($endpoint) {
   ob_end_clean();
   drupal_add_http_header('Connection', 'close', FALSE);
   drupal_add_http_header('Content-Length', drupal_strlen($wsdl_content), TRUE);
-  drupal_add_http_header('Content-Type', 'application/wsdl+xml; charset=utf-8', TRUE);
+  drupal_add_http_header('Content-Type: text/xml; charset=utf-8', TRUE);
   drupal_add_http_header('Date', date('r'), TRUE);
   echo $wsdl_content;
   exit;
@@ -224,16 +239,22 @@ class ServicesSoapServer {
     // Handle the request.
     $info =  services_server_info_object();
     $endpoint = services_endpoint_load($info->endpoint);
-    $services_method_name = str_replace('_soap_', '.', $method_name);   
+    $services_method_name = str_replace('_soap_', '.', $method_name);
     $controller = services_controller_get($services_method_name, $endpoint->name);
-    // make sure any arguments not passed have default values inserted if they are supplied 
+    $args = (array) $args[0];
+    foreach ($args as $key => $arg) {
+      if (is_object($arg)) {
+        $args[$key] = (array) $arg;
+      }
+    }
+    // make sure any arguments not passed have default values inserted if they are supplied
     // TODO: should we be validating argument types here?
     foreach ($controller['args'] as $key => $arg_config) {
       if (!isset($args[$key]) && isset($arg_config['default value'])) {
         $args[$key] = $arg_config['default value'];
       }
     }
-    
+
     if ($endpoint->debug) {
       watchdog('soap server', "METHOD_NAME:<pre>". print_r($method_name, TRUE)."</pre");
       watchdog('soap server', "ENDPOINT:<pre>". print_r($endpoint, TRUE)."</pre");
@@ -249,10 +270,50 @@ class ServicesSoapServer {
       watchdog('soap_server', $e->getMessage(), NULL, 'error');
       throw $soap_fault;
     }
+    $doc = new DOMDocument('1.0', 'utf-8');
+    $root = $doc->createElement('response_object');
+    $doc->appendChild($root);
+
+    xml_recurse($doc, $root, $ret);
+
+    $xml = $doc->saveXML();
+    $xml = str_replace('<?xml version="1.0" encoding="utf-8"?>', '', $xml);
+
+    $ret = array("{$method_name}_result" => array('any' => $xml));
     return $ret;
   }
 }
 
+function xml_recurse(&$doc, &$parent, $data) {
+  if (is_object($data)) {
+    $data = get_object_vars($data);
+  }
+
+  if (is_array($data)) {
+    $assoc = FALSE || empty($data);
+    foreach ($data as $key => $value) {
+      if (is_numeric($key)) {
+        $key = 'item';
+      }
+      else {
+        $assoc = TRUE;
+        $key = preg_replace('/[^A-Za-z0-9_]/', '_', $key);
+        $key = preg_replace('/^([0-9]+)/', '_$1', $key);
+      }
+      $element = $doc->createElement($key);
+      $parent->appendChild($element);
+      xml_recurse($doc, $element, $value);
+    }
+
+    if (!$assoc) {
+      $parent->setAttribute('is_array', 'true');
+    }
+  }
+  elseif ($data !== NULL) {
+    $parent->appendChild($doc->createTextNode($data));
+  }
+}
+
 /**
  * Return a list of service methods for the endopint
  * Method names are created from {resource}_{method} or {resource}_action_{method}
@@ -321,7 +382,7 @@ function soap_server_debug_client($endpoint, $node) {
     // show the available functions as specified in the WSDL
     $functions = $client->__getFunctions();
     $debug_output['client functions'] = $functions;
-    
+
     // retrieve a node  -  need node access for anonymous
     $return = $client->node_soap_retrieve($node->nid);
     $response = $client->__getLastResponse();
@@ -329,15 +390,15 @@ function soap_server_debug_client($endpoint, $node) {
     $debug_output["node_soap_retrieve"] = array(
       $node->nid => array('request' => $request, 'response' => $response, 'return' => $return)
     );
-    
+
     //retrieve a variable - enable services "get a system variable" permission for anonymous
     $return = $client->system_soap_get_variable('css_js_query_string');
     $response = $client->__getLastResponse();
     $request = $client->__getLastRequest();
     $debug_output["system_soap_get_variable"] = array(
       'css_js_query_string' => array('request' => $request, 'response' => $response, 'return' => $return)
-    );  
-    
+    );
+
     // retrieve a user  - needs acess for anonymous
     $return = $client->user_soap_retrieve(1);  // anonymous user needs "access user profiles" perm
     $response = $client->__getLastResponse();
@@ -345,7 +406,7 @@ function soap_server_debug_client($endpoint, $node) {
     $debug_output["user_soap_retrieve"] = array(
       1 => array('request' => $request, 'response' => $response, 'return' => $return)
     );
-    
+
   } catch (Exception $e) {
     $debug_output['client'] = $e;
   }
@@ -373,34 +434,34 @@ function soap_server_debug_wsdl($endpoint) {
 }
 
 /**
- * Make the WSDL look nice.  
- * 
+ * Make the WSDL look nice.
+ *
  * WARNING: This is NOT a general XML formatter because it will remove whitespace
  * between tags and in CDATA blocks
- * 
+ *
  * @param unknown_type $xml
  */
-function _soap_server_beautify_wsdl($xml) { 
+function _soap_server_beautify_wsdl($xml) {
   // remove whitespace between tags
   $xml = preg_replace('/(>)(\s*)(<)/', '$1$3', $xml);
   // limit spaces and tabs one space
   $xml = preg_replace('/([ \t]{2,})/', ' ', $xml);
   // add marker linefeeds to aid the pretty-tokeniser (adds a linefeed between all tag-end boundaries)
   $xml = preg_replace('/(>)\s*(<)(\/*)/', "$1\n$2$3", $xml);
-  
+
   // now indent the tags
   $token      = strtok($xml, "\n");
   $result     = ''; // holds formatted version as it is built
   $pad        = 1; // initial indent
   $matches    = array(); // returns from preg_matches()
-  
+
   // scan each line and adjust indent based on opening/closing tags
-  while ($token !== false) : 
-  
+  while ($token !== false) :
+
     // test for the various tag states
-    
+
     // 1. open and closing tags on same line - no change
-    if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) : 
+    if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) :
       $indent=0;
     // 2. closing tag - outdent now
     elseif (preg_match('/^<\/\w/', $token, $matches)) :
@@ -410,15 +471,15 @@ function _soap_server_beautify_wsdl($xml) {
       $indent=1;
     // 4. no indentation needed
     else :
-      $indent = 0; 
+      $indent = 0;
     endif;
-    
+
     // pad the line with the required number of leading spaces
     $line    = str_pad($token, strlen($token)+$pad, ' ', STR_PAD_LEFT);
     $result .= $line . "\n"; // add to the cumulative result, with linefeed
     $token   = strtok("\n"); // get the next token
-    $pad    += $indent; // update the pad size for subsequent lines    
-  endwhile; 
-  
+    $pad    += $indent; // update the pad size for subsequent lines
+  endwhile;
+
   return $result;
 }
diff --git a/wsdl/soap_server.wsdl.inc b/wsdl/soap_server.wsdl.inc
index 5afc187..8bebeda 100644
--- a/wsdl/soap_server.wsdl.inc
+++ b/wsdl/soap_server.wsdl.inc
@@ -15,7 +15,9 @@ $wsdl_content = "<?xml version='1.0' encoding='UTF-8' ?>
   
   <types>
   	<xsd:schema targetNamespace='urn:soap_server'
-      xmlns:xsd='http://www.w3.org/2001/XMLSchema' />
+      xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
+      $types
+    </xsd:schema>
   </types>
   
 $requests
@@ -27,7 +29,7 @@ $port_type_operations
   </portType>
 
   <binding name='soap_server_binding' type='tns:soap_server_port_type'>
-    <soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http' />
+    <soap:binding transport='http://schemas.xmlsoap.org/soap/http' />
 $binding_operations
   </binding>

