You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ah...@apache.org on 2019/10/03 21:16:33 UTC

[royale-asjs] 01/10: WebService compiles except for XMLDocument and getTimer

This is an automated email from the ASF dual-hosted git repository.

aharui pushed a commit to branch webservice
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git

commit b201a96b4493d7701c7f796c090d3ddb3f66a594
Author: Alex Harui <ah...@apache.org>
AuthorDate: Thu Sep 12 21:56:48 2019 -0700

    WebService compiles except for XMLDocument and getTimer
---
 .../src/main/resources/mx-royale-manifest.xml      |    2 +
 .../src/main/royale/mx/events/ErrorEvent.as        |    2 +
 .../royale/mx/messaging/messages/SOAPMessage.as    |  126 +
 .../src/main/royale/mx/rpc/events/HeaderEvent.as   |  157 ++
 .../main/royale/mx/rpc/events/SchemaLoadEvent.as   |  105 +
 .../src/main/royale/mx/rpc/events/WSDLLoadEvent.as |  149 ++
 .../src/main/royale/mx/rpc/events/XMLLoadEvent.as  |  169 ++
 .../main/royale/mx/rpc/soap/AbstractWebService.as  |  823 ++++++
 .../src/main/royale/mx/rpc/soap/ISOAPDecoder.as    |  131 +
 .../src/main/royale/mx/rpc/soap/ISOAPEncoder.as    |   83 +
 .../src/main/royale/mx/rpc/soap/LoadEvent.as       |  156 ++
 .../src/main/royale/mx/rpc/soap/Operation.as       | 1180 +++++++++
 .../src/main/royale/mx/rpc/soap/SOAPConstants.as   |  351 +++
 .../src/main/royale/mx/rpc/soap/SOAPDecoder.as     | 1031 ++++++++
 .../src/main/royale/mx/rpc/soap/SOAPEncoder.as     |  912 +++++++
 .../src/main/royale/mx/rpc/soap/SOAPFault.as       |  183 ++
 .../src/main/royale/mx/rpc/soap/SOAPHeader.as      |  120 +
 .../src/main/royale/mx/rpc/soap/SOAPResult.as      |   81 +
 .../src/main/royale/mx/rpc/soap/WebService.as      |   84 +-
 .../src/main/royale/mx/rpc/soap/mxml/Operation.as  |  272 ++
 .../src/main/royale/mx/rpc/soap/mxml/WebService.as |  376 +++
 .../royale/mx/rpc/soap/types/ApacheDocumentType.as |   55 +
 .../main/royale/mx/rpc/soap/types/DataSetType.as   |  165 ++
 .../royale/mx/rpc/soap/types/ICustomSOAPType.as    |   41 +
 .../src/main/royale/mx/rpc/soap/types/MapType.as   |  168 ++
 .../main/royale/mx/rpc/soap/types/QueryBeanType.as |  107 +
 .../main/royale/mx/rpc/soap/types/RowSetType.as    |  119 +
 .../main/royale/mx/rpc/soap/types/SOAPArrayType.as |  614 +++++
 .../MXRoyale/src/main/royale/mx/rpc/wsdl/WSDL.as   | 1366 ++++++++++
 .../src/main/royale/mx/rpc/wsdl/WSDLBinding.as     |  171 ++
 .../src/main/royale/mx/rpc/wsdl/WSDLConstants.as   |  257 ++
 .../src/main/royale/mx/rpc/wsdl/WSDLEncoding.as    |  278 ++
 .../src/main/royale/mx/rpc/wsdl/WSDLLoader.as      |  306 +++
 .../src/main/royale/mx/rpc/wsdl/WSDLMessage.as     |  203 ++
 .../src/main/royale/mx/rpc/wsdl/WSDLMessagePart.as |   78 +
 .../src/main/royale/mx/rpc/wsdl/WSDLOperation.as   |  260 ++
 .../src/main/royale/mx/rpc/wsdl/WSDLPort.as        |  132 +
 .../src/main/royale/mx/rpc/wsdl/WSDLPortType.as    |   86 +
 .../src/main/royale/mx/rpc/wsdl/WSDLService.as     |  118 +
 .../src/main/royale/mx/rpc/xml/ComplexString.as    |   56 +
 .../src/main/royale/mx/rpc/xml/ContentProxy.as     |  398 +++
 .../src/main/royale/mx/rpc/xml/DecodingContext.as  |   45 +
 .../src/main/royale/mx/rpc/xml/IXMLDecoder.as      |  135 +
 .../src/main/royale/mx/rpc/xml/IXMLEncoder.as      |  107 +
 .../main/royale/mx/rpc/xml/IXMLSchemaInstance.as   |   65 +
 .../src/main/royale/mx/rpc/xml/NamespaceUtil.as    |   81 +
 .../royale/mx/rpc/xml/QualifiedResourceManager.as  |  164 ++
 .../MXRoyale/src/main/royale/mx/rpc/xml/Schema.as  |  305 +++
 .../src/main/royale/mx/rpc/xml/SchemaConstants.as  |  309 +++
 .../src/main/royale/mx/rpc/xml/SchemaDatatypes.as  |  193 ++
 .../src/main/royale/mx/rpc/xml/SchemaLoader.as     |  258 ++
 .../src/main/royale/mx/rpc/xml/SchemaManager.as    |  550 ++++
 .../src/main/royale/mx/rpc/xml/SchemaMarshaller.as | 1513 +++++++++++
 .../src/main/royale/mx/rpc/xml/SchemaProcessor.as  |  235 ++
 .../main/royale/mx/rpc/xml/SchemaTypeRegistry.as   |  269 ++
 .../src/main/royale/mx/rpc/xml/SimpleContent.as    |   56 +
 .../src/main/royale/mx/rpc/xml/SimpleXMLDecoder.as |  240 ++
 .../src/main/royale/mx/rpc/xml/SimpleXMLEncoder.as |  284 ++
 .../src/main/royale/mx/rpc/xml/TypeIterator.as     |  194 ++
 .../src/main/royale/mx/rpc/xml/XMLDecoder.as       | 2728 ++++++++++++++++++++
 .../src/main/royale/mx/rpc/xml/XMLEncoder.as       | 1984 ++++++++++++++
 .../src/main/royale/mx/rpc/xml/XMLLoader.as        |  151 ++
 .../src/main/royale/mx/utils/Base64Decoder.as      |   62 +-
 .../src/main/royale/mx/utils/Base64Encoder.as      |   23 +-
 .../src/main/royale/mx/utils/HexDecoder.as         |  123 +
 .../src/main/royale/mx/utils/HexEncoder.as         |  182 ++
 .../MXRoyale/src/main/royale/mx/utils/XMLUtil.as   |  147 ++
 .../src/main/royale/mx/utils/object_proxy.as       |   34 +
 68 files changed, 21820 insertions(+), 88 deletions(-)

diff --git a/frameworks/projects/MXRoyale/src/main/resources/mx-royale-manifest.xml b/frameworks/projects/MXRoyale/src/main/resources/mx-royale-manifest.xml
index 3f7bf8b..74a8731 100644
--- a/frameworks/projects/MXRoyale/src/main/resources/mx-royale-manifest.xml
+++ b/frameworks/projects/MXRoyale/src/main/resources/mx-royale-manifest.xml
@@ -62,6 +62,8 @@
 	<component id="RemoteObject" class="mx.rpc.remoting.mxml.RemoteObject" />
     <component id="RemoteObjectOperation" class="mx.rpc.remoting.mxml.Operation"/>
 	<component id="HTTPService" class="mx.rpc.http.mxml.HTTPService" />
+    <component id="WebService" class="mx.rpc.soap.mxml.WebService" />
+    <component id="WebServiceOperation" class="mx.rpc.soap.mxml.Operation" />
 	<component id="NumberValidator" class="mx.validators.NumberValidator"/>
 	<component id="PhoneNumberValidator" class="mx.validators.PhoneNumberValidator"/>
 	<component id="DateValidator" class="mx.validators.DateValidator"/>
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/events/ErrorEvent.as b/frameworks/projects/MXRoyale/src/main/royale/mx/events/ErrorEvent.as
index 3bf3094..d0793b9 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/events/ErrorEvent.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/events/ErrorEvent.as
@@ -39,6 +39,8 @@ import org.apache.royale.events.IRoyaleEvent;
 COMPILE::SWF
 public class ErrorEvent extends flash.events.ErrorEvent
 {
+    public static const ERROR:String = "error";
+    
 	public function ErrorEvent(type:String, bubbles:Boolean = false,
 							  cancelable:Boolean = false, text:String = "", id:int = 0
 							  )
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/messaging/messages/SOAPMessage.as b/frameworks/projects/MXRoyale/src/main/royale/mx/messaging/messages/SOAPMessage.as
new file mode 100644
index 0000000..233e889
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/messaging/messages/SOAPMessage.as
@@ -0,0 +1,126 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.messaging.messages
+{
+
+[RemoteClass(alias="flex.messaging.messages.SOAPMessage")]
+
+/**
+ *  SOAPMessages are similar to HTTPRequestMessages. However,
+ *  they always contain a SOAP XML envelope request body
+ *  that will always be sent using HTTP POST.
+ *  They also allow a SOAP action to be specified.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion BlazeDS 4
+ *  @productversion LCDS 3 
+ */
+public class SOAPMessage extends HTTPRequestMessage
+{
+    //--------------------------------------------------------------------------
+    //
+    // Static Constants
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     *  The HTTP header that stores the SOAP action for the SOAPMessage.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion BlazeDS 4
+     *  @productversion LCDS 3 
+     */
+    public static const SOAP_ACTION_HEADER:String = "SOAPAction";    
+    
+    //--------------------------------------------------------------------------
+    //
+    // Constructor
+    // 
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Constructs an uninitialized SOAPMessage.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion BlazeDS 4
+     *  @productversion LCDS 3 
+     */
+    public function SOAPMessage()
+    {
+        super();
+        method = "POST";
+        contentType = CONTENT_TYPE_SOAP_XML;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Provides access to the name of the remote method/operation that
+     *  will be called.
+     *
+     *  @return Returns the name of the remote method/operation that 
+     *  will be called.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion BlazeDS 4
+     *  @productversion LCDS 3 
+     */
+    public function getSOAPAction():String
+    {
+        return (httpHeaders != null) ? httpHeaders[SOAP_ACTION_HEADER] : null;
+    }
+
+    /**
+     *  @private
+     */
+    public function setSOAPAction(value:String):void
+    {
+        if (value != null)
+        {
+            if (value.indexOf('"') < 0)
+            {
+                var str:String = '"';
+                str += value;
+                str += '"';
+                value = str.toString();
+            }
+
+            if (httpHeaders == null)
+                httpHeaders = {};
+
+            httpHeaders[SOAP_ACTION_HEADER] = value;
+        }
+    }
+
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/HeaderEvent.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/HeaderEvent.as
new file mode 100644
index 0000000..ddb196b
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/HeaderEvent.as
@@ -0,0 +1,157 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.events
+{
+    
+import org.apache.royale.events.IRoyaleEvent;
+import org.apache.royale.events.Event;
+
+import mx.core.mx_internal;
+import mx.messaging.messages.IMessage;
+import mx.rpc.AsyncToken;
+
+use namespace mx_internal;
+
+/**
+ * The event that indicates an RPC operation, such as a WebService SOAP request,
+ * returned a header in the response. A new header event is dispatched for each
+ * service header.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class HeaderEvent extends AbstractEvent
+{
+   /**
+    * The HEADER event type.
+    *
+    * <p>The properties of the event object have the following values:</p>
+    * <table class="innertable">
+    *     <tr><th>Property</th><th>Value</th></tr>
+    *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+    *     <tr><td><code>token</code></td><td>The token that represents the call
+    *     to the method. Used in the asynchronous completion token pattern.</td></tr>
+    *     <tr><td><code>cancelable</code></td><td>true, but the preventDefault() method has 
+    *       no effect.</td></tr>
+    *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+    *       event listener that handles the event. For example, if you use 
+    *       <code>myButton.addEventListener()</code> to register an event listener, 
+    *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+    *     <tr><td><code>header</code></td><td>Header that the RPC call returns in the response. 
+    *     </td></tr>   
+    *     <tr><td><code>message</code></td><td>The Message associated with this event.</td></tr>
+    *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+    *       it is not always the Object listening for the event. 
+    *       Use the <code>currentTarget</code> property to always access the 
+    *       Object listening for the event.</td></tr>
+    *  </table>
+    *  @eventType header 
+    *  
+    *  @langversion 3.0
+    *  @playerversion Flash 9
+    *  @playerversion AIR 1.1
+    *  @productversion Flex 3
+    */
+    public static const HEADER:String = "header";
+
+    private var _header:Object;
+
+    /**
+     * Creates a new HeaderEvent.
+     *
+     * @param type The event type; indicates the action that caused the event.
+     * @param bubbles Specifies whether the event can bubble up the display list hierarchy.
+     * @param cancelable Specifies whether the behavior associated with the event can be prevented. The dfault is <code>true</code>, but the <code>preventDefault()</code> method has no effect.
+     * @param header Object that holds the header of the call.
+     * @param token AsyncToken that represents the call to the method. Used in the asynchronous completion token pattern.
+     * @param message Source Message of the header.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function HeaderEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = true,
+            header:Object = null, token:AsyncToken = null, message:IMessage = null)
+    {
+        super(type, bubbles, cancelable, token, message);
+
+        _header = header;
+    }
+
+    /**
+     * Header that the RPC call returned in the response.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get header():Object
+    {
+        return _header;
+    }
+
+    /**
+     * Utility method to create a new HeaderEvent that doesn't bubble and is cancelable.
+     *
+     * @param header Object that holds the header of the call.
+     * @param token AsyncToken that represents the call to the method. Used in the asynchronous completion token pattern.
+     * @param message Source Message header.
+     *
+     * @return Returns a new HeaderEvent that doesn't bubble and is cancelable.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function createEvent(header:Object, token:AsyncToken, message:IMessage):HeaderEvent
+    {
+        return new HeaderEvent(HeaderEvent.HEADER, false, true, header, token, message);
+    }
+
+    /**
+      * @private
+      */
+    override public function cloneEvent():IRoyaleEvent
+    {
+        return new HeaderEvent(type, bubbles, cancelable, header, token, message);
+    }
+
+   /**
+     * Returns a string representation of the HeaderEvent.
+     *
+     * @return String representation of the HeaderEvent.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function toString():String
+    {
+        return formatToString("HeaderEvent", "type", "bubbles", "cancelable", "eventPhase");
+    }
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/SchemaLoadEvent.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/SchemaLoadEvent.as
new file mode 100644
index 0000000..98940d1
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/SchemaLoadEvent.as
@@ -0,0 +1,105 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.events
+{
+
+import org.apache.royale.events.IRoyaleEvent;
+import org.apache.royale.events.Event;
+import mx.rpc.xml.Schema;
+
+[ExcludeClass]
+
+/**
+ * This event is dispatched when an XML Schema has loaded sucessfully.
+ * 
+ * @private
+ */
+public class SchemaLoadEvent extends XMLLoadEvent
+{
+    /**
+     * Creates a new SchemaLoadEvent.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function SchemaLoadEvent(type:String, bubbles:Boolean = false, 
+        cancelable:Boolean = true, schema:Schema = null, location:String = null)
+    {
+        super(type == null ? LOAD : type,
+            bubbles,
+            cancelable,
+            schema == null ? null : schema.xml,
+            location);
+
+        this.schema = schema;
+    }
+
+    /**
+     * The full Schema document.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var schema:Schema;
+
+    /**
+     * Returns a copy of this SchemaLoadEvent.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function cloneEvent():IRoyaleEvent
+    {
+        return new SchemaLoadEvent(type, bubbles, cancelable, schema, location);
+    }
+
+    /**
+     * Returns a String representation of this SchemaLoadEvent.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function toString():String
+    {
+        return formatToString("SchemaLoadEvent", "location", "type", "bubbles",
+            "cancelable", "eventPhase");
+    }
+
+    /**
+     * A helper method to create a new SchemaLoadEvent.
+     * @private
+     */
+    public static function createEvent(schema:Schema, location:String = null):SchemaLoadEvent
+    {
+        return new SchemaLoadEvent(LOAD, false, true, schema, location);
+    }
+
+    public static const LOAD:String = "schemaLoad";
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/WSDLLoadEvent.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/WSDLLoadEvent.as
new file mode 100644
index 0000000..84dde55
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/WSDLLoadEvent.as
@@ -0,0 +1,149 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.events
+{
+
+import org.apache.royale.events.Event;
+import org.apache.royale.events.IRoyaleEvent;
+import mx.rpc.wsdl.WSDL;
+
+/**
+ * The WSDLLoadEvent class represents the event object for the event dispatched 
+ * when a WSDL XML document has loaded successfully.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class WSDLLoadEvent extends XMLLoadEvent
+{
+    /**
+     * Constructor.
+     *
+     * @param type The event type; indicates the action that caused the event.
+     *
+     * @param bubbles Specifies whether the event can bubble up the display list hierarchy.
+     *
+     * @param cancelable Specifies whether the behavior associated with the event can be prevented.
+     *
+     * @param wsdl The full WSDL document.
+     *
+     * @param location The path used to load the document.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function WSDLLoadEvent(type:String, bubbles:Boolean = false, 
+        cancelable:Boolean = true, wsdl:WSDL = null, location:String = null)
+    {
+        super(type == null ? LOAD : type,
+            bubbles,
+            cancelable,
+            wsdl == null ? null : wsdl.xml,
+            location);
+
+        this.wsdl = wsdl;
+    }
+
+    /**
+     * The full WSDL document.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var wsdl:WSDL
+
+    /**
+     *  Returns a copy of this WSDLLoadEvent object.
+     *
+     *  @return A copy of this WSDLLoadEvent object.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function cloneEvent():IRoyaleEvent
+    {
+        return new WSDLLoadEvent(type, bubbles, cancelable, wsdl, location);
+    }
+
+    /**
+     *  Returns a String representation of this WSDLLoadEvent object.
+     *
+     *  @return A String representation of this WSDLLoadEvent object.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function toString():String
+    {
+        return formatToString("WSDLLoadEvent", "location", "type", "bubbles",
+            "cancelable", "eventPhase");
+    }
+
+    /**
+     * A helper method to create a new WSDLLoadEvent.
+     * @private
+     */
+    public static function createEvent(wsdl:WSDL, location:String = null):WSDLLoadEvent
+    {
+        return new WSDLLoadEvent(LOAD, false, true, wsdl, location);
+    }
+
+    /**
+     * The LOAD constant defines the value of the <code>type</code> property of the event object 
+     * for a <code>wsdlLoad</code> event.
+     *
+     * <p>The properties of the event object have the following values:</p>
+     * <table class="innertable">
+     * <tr><th>Property</th><th>Value</th></tr>
+     * <tr><td><code>bubbles</code></td><td><code>false</code></td></tr>
+     * <tr><td><code>cancelable</code></td><td><code>true</code></td></tr>
+     * <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *     event listener that handles the event. For example, if you use 
+     *     <code>myButton.addEventListener()</code> to register an event listener, 
+     *     myButton is the value of the <code>currentTarget</code>. </td></tr>
+     * <tr><td><code>location</code></td><td>The path used to load the document.</td></tr>
+     * <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *     it is not always the Object listening for the event. 
+     *     Use the <code>currentTarget</code> property to always access the 
+     *     Object listening for the event.</td></tr>
+     * <tr><td><code>wsdl</code></td><td>The full WSDL document.</td></tr>
+     * </table>
+     *     
+     * @eventType result      
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static const LOAD:String = "wsdlLoad";
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/XMLLoadEvent.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/XMLLoadEvent.as
new file mode 100644
index 0000000..323bfcd
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/events/XMLLoadEvent.as
@@ -0,0 +1,169 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.events
+{
+
+import org.apache.royale.events.Event;
+import org.apache.royale.events.IRoyaleEvent;
+
+/**
+ * The XMLLoadEvent class is a base class for events that are dispatched when an RPC service
+ * successfully loaded an XML document.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class XMLLoadEvent extends Event
+{
+    /**
+     * Constructor.
+     *
+     * @param type The event type; indicates the action that triggered the event.
+     *
+     * @param bubbles Specifies whether the event can bubble up the display list hierarchy.
+     *
+     * @param cancelable Specifies whether the behavior associated with the event can be prevented.
+     *
+     * @param xml The XML document loaded.
+     *
+     * @param location The path used to load the document.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function XMLLoadEvent(type:String, bubbles:Boolean = false, 
+        cancelable:Boolean = true, xml:XML = null, location:String = null)
+    {
+        super(type == null ? LOAD : type,
+            bubbles,
+            cancelable);
+
+        this.xml = xml;
+        this.location = location;
+    }
+
+    /**
+     * The raw XML document.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var xml:XML;
+
+    /**
+     * The location from which the document was loaded.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var location:String;
+
+    /**
+     *  Returns a copy of this XMLLoadEvent object.
+     *
+     *  @return A copy of this XMLLoadEvent object.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function cloneEvent():IRoyaleEvent
+    {
+        return new XMLLoadEvent(type, bubbles, cancelable, xml, location);
+    }
+
+    /**
+     *  Returns a String representation of this XMLLoadEvent object.
+     *
+     *  @return A String representation of this XMLLoadEvent object.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    COMPILE::SWF {override}
+    public function toString():String
+    {
+        return formatToString("XMLLoadEvent", "location", "type", "bubbles", 
+            "cancelable", "eventPhase");
+    }
+
+    COMPILE::JS
+    public function formatToString(className:String, ... rest):String
+    {
+        if (rest)
+        {
+            for (var s:String in rest)
+                className += " " + s;
+        }
+        return className;
+    }
+    
+    /**
+     * A helper method to create a new XMLLoadEvent.
+     * @private
+     */
+    public static function createEvent(xml:XML = null, location:String = null):XMLLoadEvent
+    {
+        return new XMLLoadEvent(LOAD, false, true, xml, location);
+    }
+
+    /**
+     * The LOAD constant defines the value of the <code>type</code> property of the event object 
+     * for a <code>xmlLoad</code> event.
+     *
+     * <p>The properties of the event object have the following values:</p>
+     * <table class="innertable">
+     * <tr><th>Property</th><th>Value</th></tr>
+     * <tr><td><code>bubbles</code></td><td><code>false</code></td></tr>
+     * <tr><td><code>cancelable</code></td><td><code>true</code></td></tr>
+     * <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *     event listener that handles the event. For example, if you use 
+     *     <code>myButton.addEventListener()</code> to register an event listener, 
+     *     myButton is the value of the <code>currentTarget</code>. </td></tr>
+     * <tr><td><code>location</code></td><td>The location from which the document was loaded.</td></tr>
+     * <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *     it is not always the Object listening for the event. 
+     *     Use the <code>currentTarget</code> property to always access the 
+     *     Object listening for the event.</td></tr>
+     * <tr><td><code>xml</code></td><td>The raw XML document.</td></tr>
+     * </table>
+     *     
+     * @eventType result      
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static const LOAD:String = "xmlLoad";
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/AbstractWebService.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/AbstractWebService.as
new file mode 100644
index 0000000..a94c3fa
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/AbstractWebService.as
@@ -0,0 +1,823 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+import org.apache.royale.events.Event;
+
+import mx.core.mx_internal;
+import mx.logging.ILogger;
+import mx.logging.Log;
+import mx.messaging.ChannelSet;
+import mx.messaging.channels.DirectHTTPChannel;
+import mx.messaging.config.LoaderConfig;
+import mx.rpc.AbstractOperation;
+import mx.rpc.AbstractService;
+import mx.rpc.AsyncRequest;
+import mx.rpc.Fault;
+import mx.rpc.events.FaultEvent;
+import mx.rpc.http.HTTPService;
+import mx.utils.URLUtil;
+import mx.utils.XMLUtil;
+
+use namespace mx_internal;
+
+/**
+ *  AbstractWebService is an abstract base class for implementations 
+ *  that provide RPC access to SOAP-based web services. This class does not
+ *  load WSDL descriptions at runtime.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class AbstractWebService extends AbstractService
+{
+    //--------------------------------------------------------------------------
+    //
+    // Constructor
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Creates a new WebService.  The destination, if specified, should match an
+     * entry in services-config.xml.  If unspecified, the WebService uses the
+     * DefaultHTTP destination. The <code>rootURL</code> is required if you
+     * intend to use a relative URL find the WSDL document for this WebService.
+     *
+     *  @param destination The destination. It should match a destination name 
+     *  in the services-config.xml file.
+     *
+     *  @param rootURL The URL that the WebService should use when computing relative URLs.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function AbstractWebService(destination:String = null, rootURL:String = null)
+    {
+        super(destination);
+
+        _useProxy = false;
+        _headers = [];
+        _log = Log.getLogger("mx.rpc.soap.AbstractWebService");
+
+        if (destination == null)
+        {
+            // If the SWF was loaded via HTTPS, we'll use the DefaultHTTPS
+            // destination by default
+            if (URLUtil.isHttpsURL(LoaderConfig.url))
+                super.destination = DEFAULT_DESTINATION_HTTPS;
+            else
+                super.destination = DEFAULT_DESTINATION_HTTP;
+
+            destinationSet = false;
+        }
+        else
+        {
+            destinationSet = true;
+        }
+
+        makeObjectsBindable = true;
+
+        _ready = true;
+    }
+
+    //-------------------------------------------------------------------------
+    //
+    // Properties
+    //
+    //-------------------------------------------------------------------------
+
+    //----------------------------------
+    //  description
+    //----------------------------------
+
+    /**
+     * The description of the service for the currently active port.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get description():String
+    {
+        return _description;
+    }
+
+    public function set description(value:String):void
+    {
+        _description = value;
+    }
+
+
+    //----------------------------------
+    //  destination
+    //----------------------------------
+
+    /**
+     * @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function get destination():String
+    {
+        return super.destination;
+    }
+
+    override public function set destination(value:String):void
+    {
+        super.destination = value;
+        useProxy = true;
+        destinationSet = true;
+    }
+
+
+    //----------------------------------
+    //  endpointURI
+    //----------------------------------
+
+    /**
+     * The location of the WebService. Normally, the WSDL document specifies
+     * the location of the services, but you can set this property to override
+     * that location.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get endpointURI():String
+    {
+        return (endpointOverride) ? endpointOverride : _endpointURI;
+    }
+
+    public function set endpointURI(value:String):void
+    {
+        endpointOverride = value;
+    }
+
+
+    //----------------------------------
+    //  headers
+    //----------------------------------
+
+    /**
+     * Returns the array of SOAPHeaders registered for the WebService.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get headers():Array
+    {
+        return _headers;
+    }
+
+
+    //----------------------------------
+    //  httpHeaders
+    //----------------------------------
+
+    private var _httpHeaders:Object;
+
+    [Inspectable(defaultValue="undefined", category="General")]
+    /**
+     * Custom HTTP headers to be sent to the SOAP endpoint. If multiple
+     * headers need to be sent with the same name the value should be specified
+     * as an Array.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get httpHeaders():Object
+    {
+        return _httpHeaders;
+    }
+
+    public function set httpHeaders(value:Object):void
+    {
+        _httpHeaders = value;
+    }
+
+
+    //----------------------------------
+    //  makeObjectsBindable
+    //----------------------------------
+
+    [Inspectable(defaultValue="true", category="General")]
+    /**
+     * When this value is true, anonymous objects returned are forced to
+     * bindable objects.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get makeObjectsBindable():Boolean
+    {
+        return _makeObjectsBindable;
+    }
+
+    public function set makeObjectsBindable(value:Boolean):void
+    {
+        _makeObjectsBindable = value;
+    }
+
+
+    //----------------------------------
+    //  port
+    //----------------------------------
+
+    /**
+     * Specifies the port within the WSDL document that this WebService should
+     * use.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get port():String
+    {
+        return _port;
+    }
+
+    public function set port(value:String):void
+    {
+        _port = value;
+    }
+
+
+    //----------------------------------
+    //  ready
+    //----------------------------------
+
+    /**
+     * Specifies whether the WebService is ready to make requests.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get ready():Boolean
+    {
+        return _ready;
+    }
+
+
+    //----------------------------------
+    //  rootURL
+    //----------------------------------
+
+    /**
+     * The URL that the WebService should use when computing relative URLs. This
+     * property is only used when going through the proxy. When the
+     * <code>useProxy</code> property is set <code>to false</code> the relative
+     * URL is computed automatically based on the location of the SWF running
+     * this application. If not set explicitly <code>rootURL</code> is
+     * automatically set to the URL of mx.messaging.config.LoaderConfig.url.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get rootURL():String
+    {
+        if (_rootURL == null)
+        {
+            _rootURL = LoaderConfig.url;
+        }
+        return _rootURL;
+    }
+
+    public function set rootURL(value:String):void
+    {
+        _rootURL = value;
+    }
+
+
+    //----------------------------------
+    //  service
+    //----------------------------------
+
+    /**
+     * Specifies the service within the WSDL document that this WebService
+     * should use.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get service():String
+    {
+        return _service;
+    }
+
+    public function set service(value:String):void
+    {
+        _service = value;
+    }
+
+
+    //----------------------------------
+    //  useProxy
+    //----------------------------------
+
+    [Inspectable(defaultValue="false", category="General")]
+    /**
+     * Specifies whether to use the Flex proxy service. The default value is
+     * <code>false</code>. If you do not specify <code>true</code> to proxy
+     * requests though the Flex server, you must ensure that Flash Player can
+     * reach the target URL. You also cannot use destinations defined in the
+     * services-config.xml file if the <code>useProxy</code> property is set
+     * to <code>false</code>.
+     *
+     * @default false
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get useProxy():Boolean
+    {
+        return _useProxy;
+    }
+
+    public function set useProxy(value:Boolean):void
+    {
+        if (value != _useProxy)
+        {
+            _useProxy = value;
+
+            var dcs:ChannelSet = getDirectChannelSet();
+            if (!useProxy)
+            {
+                if (dcs != asyncRequest.channelSet)
+                    asyncRequest.channelSet = dcs;
+            }
+            else
+            {
+                if (asyncRequest.channelSet == dcs)
+                    asyncRequest.channelSet = null;
+            }
+        }
+    }
+
+
+    //----------------------------------
+    //  xmlSpecialCharsFilter
+    //----------------------------------
+
+    private var _xmlSpecialCharsFilter:Function;
+
+    [Inspectable(defaultValue="undefined", category="General")]
+    /**
+     *  Custom function to be used to escape XML special characters before
+     *  encoding any simple content. Valid for all operations on the web
+     *  service unless specifically overwritten on the operation level.
+     *  If none is provided, the default function is whatever is set by the particular
+     *  implementation of IXMLEncoder.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get xmlSpecialCharsFilter():Function
+    {
+        return _xmlSpecialCharsFilter;
+    }
+
+    public function set xmlSpecialCharsFilter(func:Function):void
+    {
+        _xmlSpecialCharsFilter = func;
+    }
+
+    //----------------------------------
+    //  convertParametersHandler
+    //----------------------------------
+
+   /**
+     * An optional function, primarily intended for framework developers who need to install
+     * a function to get called with the parameters passed to each webservice operation invocation.
+     * The function takes an array of parameters and returns the potentially altered array.
+     *
+     * The function definition should look like:
+     * <code>
+     *   function myParametersFunction(parameters:Array):Array
+     * </code>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var convertParametersHandler:Function;
+
+    //----------------------------------
+    //  convertResultHandler
+    //----------------------------------
+
+    /**
+     * An optional function, primarily intended for framework developers who need to install
+     * a hook to process the results of an operation before notifying the result handlers.
+     *
+     * The function definition should look like:
+     * <code>
+     *   function myConvertResultsFunction(result:*, operation:AbstractOperation):*
+     * </code>
+     * 
+     * It is passed the result just after the makeObjectsBindable conversion has been done
+     * but before the result event is created.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var convertResultHandler:Function;
+
+    //-------------------------------------------------------------------------
+    //
+    // Methods
+    //
+    //-------------------------------------------------------------------------
+
+    /**
+     * Adds a header that will be applied to all operations of this web service.
+     * The header can be provided in a pre-encoded form as an XML instance, or
+     * as a SOAPHeader instance which leaves the encoding up to the internal
+     * SOAP encoder.
+     *  
+     * @param header The SOAP header to add to all operations.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function addHeader(header:Object):void
+    {
+        _headers.push(header);
+    }
+
+    /**
+     * Add a header that will be applied to all operations of this WebService.
+     *  
+     * @param qnameLocal The localname for the header QName.
+     * @param qnameNamespace The namespace for the header QName.
+     * @param headerName The name of the header.
+     * @param headerValue The value of the header.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function addSimpleHeader(qnameLocal:String, qnameNamespace:String, headerName:String, headerValue:String):void
+    {
+        var obj:Object = {};
+        obj[headerName] = headerValue;
+        addHeader(new SOAPHeader(new QName(qnameNamespace, qnameLocal), obj));
+    }
+
+    /**
+     * Clears the headers that applied to all operations.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function clearHeaders():void
+    {
+        _headers.length = 0;
+    }
+
+    /**
+     * Returns a header if a match is found based on QName, localName, and URI.
+     *  
+     * @param qname QName of the SOAPHeader.
+     * @param headerName (Optional) Name of a header in the SOAPHeader content.
+     *
+     * @return Returns a header if a match is found based on QName, localName, and URI.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function getHeader(qname:QName, headerName:String = null):SOAPHeader
+    {
+        var length:uint = _headers.length;
+        for (var i:uint = 0; i < length; i++)
+        {
+            var header:SOAPHeader = SOAPHeader(_headers[i]);
+            if (XMLUtil.qnamesEqual(header.qname, qname))
+            {
+                if (headerName)
+                {
+                    if (header.content && header.content[headerName])
+                    {
+                        return header;
+                    }
+                }
+                else
+                {
+                    return header;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Removes the header with the given QName from all operations.
+     *  
+     * @param qname QName of the SOAPHeader.
+     * @param headerName (Optional) Name of a header in the SOAPHeader content.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function removeHeader(qname:QName, headerName:String = null):void
+    {
+        var length:uint = _headers.length;
+        for (var i:uint = 0; i < length; i++)
+        {
+            var header:SOAPHeader = SOAPHeader(_headers[i]);
+            if (XMLUtil.qnamesEqual(header.qname, qname))
+            {
+                if (headerName)
+                {
+                    if (header.content && header.content[headerName])
+                    {
+                        _headers.splice(i, 1);
+                        return; // Got it
+                    }
+                }
+                else
+                {
+                    _headers.splice(i, 1);
+                    return; // Got it
+                }
+            }
+        }
+    }
+
+    /**
+     * The username and password to authenticate a user when accessing
+     * the webservice.  These will be passed as part of the HTTP Authorization
+     * header from the proxy to the endpoint. If useProxy is false this property
+     * will be ignored.
+     *
+     * @param remoteUsername The username to pass to the remote endpoint.
+     * @param remotePassword The password to pass to the remote endpoint.
+     * @param charset The character set encoding to use while encoding the
+     * remote credentials. The default is null, which implies the legacy charset
+     * of ISO-Latin-1. The only other supported charset is &quot;UTF-8&quot;.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function setRemoteCredentials(remoteUsername:String, remotePassword:String, charset:String=null):void
+    {
+        super.setRemoteCredentials(remoteUsername, remotePassword, charset);
+    }
+
+    //---------------------------------
+    // Helper methods
+    //---------------------------------
+
+    /**
+     * Returns a JSESSIOND found in the URL.  This should be attached
+     * to any communication back with the server where session state needs to
+     * be preserved
+     * @private
+     */
+    mx_internal static function findJSessionID():String
+    {
+        var jsessionid:String = null;
+        var args:Object = LoaderConfig.parameters;
+        if (args)
+        {
+            var js:Object = args.jsessionid;
+            if (!js)
+            {
+                js = args.JSESSIONID;
+
+                if (!js)
+                {
+                    var u:String = LoaderConfig.url;
+                    if (u)
+                    {
+                        var ind:Number = u.lastIndexOf(";")
+                        if (ind != -1)
+                        {
+                            var arr:Array = u.substring(ind + 1).split("=");
+
+                            if (arr[0] == "jsessionid" || arr[0] == "JSESSIONID")
+                            {
+                                jsessionid = arr[1];
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    jsessionid = String(js);
+                }
+            }
+            else
+            {
+                jsessionid = String(js);
+            }
+        }
+        return jsessionid;
+    }
+
+    /**
+     * @private
+     */
+    mx_internal function getDirectChannelSet():ChannelSet
+    {
+        if (_directChannelSet == null)
+        {
+            var dcs:ChannelSet = new ChannelSet();
+            var dhc:DirectHTTPChannel = new DirectHTTPChannel("direct_http_channel");
+            dhc.requestTimeout = requestTimeout;
+            dcs.addChannel(dhc);
+            _directChannelSet = dcs;            
+        }
+        return _directChannelSet;  
+    }
+
+    // Deals with the queued calls - if a fault is passed, we'll simply dispatch
+    // a FaultEvent for each call.  Otherwise we invoke each one.
+    /**
+     * @private
+     */
+    protected function unEnqueueCalls(fault:Fault = null):void
+    {
+        var op:Operation;
+        for (var opName:String in _operations)
+        {
+            op = _operations[opName];
+            if (op.hasPendingInvocations())
+            {
+                if (fault != null)
+                {
+                    _log.info("Faulting previously queued operation calls {0}", op.name);
+                    while (op.hasPendingInvocations())
+                    {
+                        op.cancel();
+                        op.dispatchEvent(FaultEvent.createEvent(fault));
+                    }
+                }
+                else
+                {
+                    _log.info("Invoking previously queued calls {0}", op.name);
+                    op.invokeAllPending();
+                }
+            }
+        }
+    }
+
+    //-------------------------------------------------------------------------
+    //
+    // Variables
+    //
+    //-------------------------------------------------------------------------
+
+    //--------------------------------------------
+    // Backing variables for public getter/setters
+    //--------------------------------------------
+
+    /**
+     * @private
+     */
+    protected var _endpointURI:String;
+ 
+    private var _description:String;
+ 
+    private var endpointOverride:String;
+ 
+    private var _headers:Array;
+ 
+    private var _makeObjectsBindable:Boolean;
+ 
+    /**
+     * @private
+     */
+    protected var _port:String;
+
+    private var _rootURL:String;
+
+    /**
+     * @private
+     */
+    protected var _service:String;
+
+    private var _useProxy:Boolean;
+
+    //---------------------------------
+    // Internal properties
+    //---------------------------------
+ 
+    //private var _activePort:Object;
+ 
+    /**
+     * @private
+     */
+    protected var destinationSet:Boolean;
+ 
+    /**
+     * @private
+     */
+    protected var _ready:Boolean;
+ 
+    private var _log:ILogger;
+
+    /**
+     * @private
+     */
+    private static var _directChannelSet:ChannelSet = null;
+
+    //--------------------------------------------------------------------------
+    //
+    // Static Constants
+    // 
+    //--------------------------------------------------------------------------
+
+
+    /**
+     * The default destination to use for HTTP connections when invoking a webservice through a proxy. 
+     * If you don't provide a destination and you set the <code>useProxy</code> property to <code>true</code>, 
+     * the default destinations will be used to route the requests to the webservice endpoint. 
+     * 
+     * <p>Note that if the default destinations are used, you must specify the WSDL and endpointURI on the client. 
+     * If you use a non-default proxy destination, you can have the WSDL and endpointURI specified in the 
+     * destination configuration.</p>
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static const DEFAULT_DESTINATION_HTTP:String = "DefaultHTTP";
+
+    /**
+     * The default destination to use for HTTPS connections when invoking a webservice through a proxy. 
+     * If you don't provide a destination and you set the <code>useProxy</code> property to <code>true</code>, 
+     * the default destinations will be used to route the requests to the webservice endpoint. 
+     * 
+     * <p>Note that if the default destinations are used, you must specify the WSDL and endpointURI on the client. 
+     * If you use a non-default proxy destination, you can have the WSDL and endpointURI specified in the 
+     * destination configuration.</p>
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static const DEFAULT_DESTINATION_HTTPS:String = "DefaultHTTPS";
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/ISOAPDecoder.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/ISOAPDecoder.as
new file mode 100644
index 0000000..8770a02
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/ISOAPDecoder.as
@@ -0,0 +1,131 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+import mx.rpc.wsdl.WSDLOperation;
+import mx.rpc.xml.IXMLDecoder;
+import mx.rpc.xml.SchemaConstants;
+
+[ExcludeClass]
+
+/**
+ * Decodes the SOAP response for a particular operation.
+ * 
+ */
+public interface ISOAPDecoder extends IXMLDecoder
+{
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Determines whether or not a single or empty return value for an output
+     * message part that is defined as an array should be returned as an array
+     * containing one (or zero, respectively) elements. This is applicable for
+     * document/literal "wrapped" web services, where one or more of the elements
+     * that represent individual message parts in the "wrapper" sequence could
+     * have the maxOccurs attribute set with a value greater than 1. This is a
+     * hint that the corresponding part should be treated as an array even if
+     * the response contains zero or one values for that part. Setting
+     * forcePartArrays to true will always create an array for parts defined in
+     * this manner, regardless of the number of values returned. Leaving
+     * forcePartArrays as false will only create arrays if two or more elements
+     * are returned.
+     */
+    function get forcePartArrays():Boolean;
+    function set forcePartArrays(value:Boolean):void;
+
+    /**
+     * Determines whether the decoder should ignore whitespace when processing
+     * the XML of a SOAP-encoded response. The default should be
+     * <code>true</code> and thus whitespace not preserved. If an XML Schema
+     * type definition specifies a <code>whiteSpace</code> restriction set to
+     * <code>preserve</code> then ignoreWhitespace must first be set to <code>false</code>.
+     * Conversely, if a type <code>whiteSpace</code> restriction is set to
+     * <code>replace</code> or <code>collapse</code> then that setting is
+     * be honored even if ignoreWhitespace is set to <code>false</code>.
+     */
+    function get ignoreWhitespace():Boolean;
+    function set ignoreWhitespace(value:Boolean):void;
+
+    /**
+     * Determines how the SOAP-encoded XML result is decoded. A value of
+     * <code>object</code> specifies that the XML is decoded into an
+     * object structure as specified in the WSDL document. A value of
+     * <code>xml</code> specifies that the XML is left as XMLNodes. A
+     * value of <code>e4x</code> specifies that the XML will be accessible
+     * using ECMAScript for XML (E4X) expressions.
+     */
+    function get resultFormat():String;
+    function set resultFormat(value:String):void;
+
+    /**
+     * Determines how the SOAP-encoded headers are decoded. A value of
+     * <code>object</code> specifies that each header XML node is decoded
+     * into a SOAPHeader object, and its <code>content</code> property is
+     * an object structure as specified in the WSDL document. A value of
+     * <code>xml</code> specifies that the XML is left as XMLNodes. A
+     * value of <code>e4x</code> specifies that the XML should be accessible
+     * using ECMAScript for XML (E4X) expressions.
+     */
+    function get headerFormat():String;
+    function set headerFormat(value:String):void;
+    
+    /**
+     * Determines the type of the default result object for calls to web services
+     * that define multiple parts in the output message. A value of "object"
+     * specifies that the lastResult object will be an Object with named properties
+     * corresponding to the individual output parts. A value of "array" would
+     * make the lastResult an array, where part values are pushed in the order
+     * they occur in the body of the SOAP message. The default value for document-
+     * literal web services is "object". The default for rpc services is "array".
+     * The multiplePartsFormat property is applicable only when
+     * resultFormat="object" and ignored otherwise.
+     */
+    function get multiplePartsFormat():String;
+    function set multiplePartsFormat(value:String):void;
+
+    /**
+     * A WSDLOperation defines the SOAP binding styles and specifies how to
+     * decode a SOAP result.
+     */
+    function get wsdlOperation():WSDLOperation;
+    function set wsdlOperation(value:WSDLOperation):void;
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Decodes a SOAP response into a result and headers.
+     *
+     *  @param response The SOAP response object.
+     *
+     *  @return A SOAPResult object containing the response. 
+     */
+    function decodeResponse(response:*):SOAPResult;
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/ISOAPEncoder.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/ISOAPEncoder.as
new file mode 100644
index 0000000..154d2f7
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/ISOAPEncoder.as
@@ -0,0 +1,83 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+import mx.rpc.wsdl.WSDLOperation;
+import mx.rpc.xml.SchemaConstants;
+import mx.rpc.xml.IXMLEncoder;
+
+[ExcludeClass]
+
+/**
+ * An ISOAPEncoder is used to create SOAP 1.1 formatted requests for a web
+ * service operation. A WSDLOperation provides the definition of how a SOAP
+ * request should be formatted and therefore must be set before a call is made to
+ * encode().
+ * 
+ */
+public interface ISOAPEncoder extends IXMLEncoder
+{
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Determines whether the encoder should ignore whitespace when
+     * constructing an XML representation of a SOAP request.
+     * The default should be <code>true</code> and thus whitespace not preserved.
+     * If an XML Schema type definition specifies a <code>whiteSpace</code>
+     * restriction set to <code>preserve</code> then ignoreWhitespace must
+     * first be set to false. Conversely, if a type <code>whiteSpace</code>
+     * restriction is set to <code>replace</code> or <code>collapse</code> then
+     * that setting will be honored even if ignoreWhitespace is set to <code>false</code>.
+     */
+    function get ignoreWhitespace():Boolean;
+    function set ignoreWhitespace(value:Boolean):void;
+
+    /**
+     * A WSDLOperation defines the SOAP binding styles and specifies how to
+     * encode a SOAP request.
+     */
+    function get wsdlOperation():WSDLOperation;
+    function set wsdlOperation(value:WSDLOperation):void;
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Creates a SOAP-encoded request to an operation from the given input
+     * parameters and headers.
+	 * 
+	 * @param args values to be encoded in the body of the SOAP request.
+	 * 
+	 * @param headers header values to be encoded in the SOAP envelope.
+     * 
+     * @return SOAP-encoded XML representation of the passed in arguments and headers.
+     */
+    function encodeRequest(args:* = null, headers:Array = null):XML;
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/LoadEvent.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/LoadEvent.as
new file mode 100644
index 0000000..8f6a857
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/LoadEvent.as
@@ -0,0 +1,156 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+import org.apache.royale.events.Event;
+import org.apache.royale.events.IRoyaleEvent;
+import flash.xml.XMLDocument;
+import mx.rpc.events.WSDLLoadEvent;
+import mx.rpc.wsdl.WSDL;
+
+// Note that this event is retained in the mx.rpc.soap package
+// for backwards compatibility.
+
+/**
+ * This event is dispatched when a WSDL XML document has loaded successfully.   
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class LoadEvent extends WSDLLoadEvent
+{
+    /**
+     * Creates a new WSDLLoadEvent.
+     * @param type The event type; indicates the action that triggered the event.
+     * @param bubbles Specifies whether the event can bubble up the display list hierarchy.
+     * @param cancelable Specifies whether the behavior associated with the event can be prevented.
+     * @param wsdl Object that contains the WSDL document.
+     * @param location URL of the WSDL document.     
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function LoadEvent(type:String, bubbles:Boolean = false, 
+        cancelable:Boolean = true, wsdl:WSDL = null, location:String = null)
+    {
+        super(type == null ? LOAD : type,
+            bubbles,
+            cancelable,
+            wsdl,
+            location);
+    }
+
+    [Deprecated(replacement="xml")]
+    /**
+     * This getter is retained to provide legacy access to the loaded document
+     * as an instance of flash.xml.XMLDocument.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get document():XMLDocument
+    {
+        if (_document == null && xml != null)
+        {
+            try
+            {
+                _document = new XMLDocument(xml.toXMLString());
+            }
+            catch(e:Error)
+            {
+            }
+        }
+        return _document;
+    }
+
+    /**
+     * Returns a copy of this LoadEvent.
+     *
+     * @return Returns a copy of this LoadEvent.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function cloneEvent():IRoyaleEvent
+    {
+        return new LoadEvent(type, bubbles, cancelable, wsdl, location);
+    }
+
+    /**
+     * Returns a String representation of this LoadEvent.
+     *
+     * @return Returns a String representation of this LoadEvent.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function toString():String
+    {
+        return formatToString("LoadEvent", "location", "type", "bubbles",
+            "cancelable", "eventPhase");
+    }
+
+    /**
+     * A helper method to create a new LoadEvent.
+     * @private
+     */
+    public static function createEvent(wsdl:WSDL, location:String = null):LoadEvent
+    {
+        return new LoadEvent(LOAD, false, true, wsdl, location);
+    }
+
+
+  /**
+    * The <code>LOAD</code> constant defines the value of the <code>type</code> property
+    * of the event object for a <code>load</code> event.
+    *
+    * <p>The properties of the event object have the following values:</p>
+    * <table class="innertable">
+    *     <tr><th>Property</th><th>Value</th></tr>
+    *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+    *     <tr><td><code>cancelable</code></td><td>true</td></tr>
+    *     <tr><td><code>wsdl</code></td><td>WSDL object.</td></tr>
+    *     <tr><td><code>location</code></td><td>URI of the WSDL document</td></tr>
+    *  </table>
+    *
+    *  @eventType load 
+    *  
+    *  @langversion 3.0
+    *  @playerversion Flash 9
+    *  @playerversion AIR 1.1
+    *  @productversion Flex 3
+    */    
+    public static const LOAD:String = "load";
+
+    private var _document:XMLDocument;
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/Operation.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/Operation.as
new file mode 100644
index 0000000..6243d69
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/Operation.as
@@ -0,0 +1,1180 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+import org.apache.royale.events.Event;
+import flash.xml.XMLNode;
+
+import mx.core.mx_internal;
+import mx.logging.Log;
+import mx.logging.ILogger;
+import mx.messaging.ChannelSet;
+import mx.messaging.events.MessageEvent;
+import mx.messaging.events.MessageFaultEvent;
+import mx.messaging.messages.IMessage;
+import mx.messaging.messages.SOAPMessage;
+import mx.netmon.NetworkMonitor;
+import mx.resources.IResourceManager;
+import mx.resources.ResourceManager;
+import mx.rpc.AbstractOperation;
+import mx.rpc.AbstractService;
+import mx.rpc.AsyncToken;
+import mx.rpc.Fault;
+import mx.rpc.events.FaultEvent;
+import mx.rpc.events.HeaderEvent;
+import mx.rpc.events.ResultEvent;
+import mx.rpc.soap.AbstractWebService;
+import mx.rpc.wsdl.WSDLOperation;
+import mx.rpc.xml.SchemaConstants;
+import mx.utils.ObjectProxy;
+import mx.utils.XMLUtil;
+
+use namespace mx_internal;
+
+/**
+ * Dispatched when an Operation invocation returns with SOAP headers in the
+ * response. A HeaderEvent is dispatched for each SOAP header.
+ * @eventType mx.rpc.events.HeaderEvent.HEADER
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="header", type="mx.rpc.events.HeaderEvent")]
+
+[ResourceBundle("rpc")]
+
+/**
+ * An Operation used specifically by WebServices. An Operation is an individual
+ * method on a service. An Operation can be called either by invoking the
+ * function of the same name on the service or by accessing the Operation as a
+ * property on the service and calling the <code>send()</code> method.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class Operation extends AbstractOperation
+{
+    //--------------------------------------------------------------------------
+    //
+    // Constructor
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Creates a new Operation. This is usually done directly by the MXML
+     * compiler or automatically by the WebService when an unknown operation
+     * has been accessed. It is not recommended that a developer use this
+     * constructor directly.
+     *
+     * @param webService The web service upon which this Operation is invoked.
+     *
+     * @param name The name of this Operation.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function Operation(webService:AbstractService = null, name:String = null)
+    {
+        super(webService, name);
+
+        _resultFormat = "object";
+        _headerFormat = "e4x";
+        _headers = [];
+        log = Log.getLogger("mx.rpc.soap.Operation");
+
+        if (webService)
+        {
+            this.webService = AbstractWebService(webService);
+            log.info("Creating SOAP Operation for {0}", name);
+        }
+
+        // No explicit timeout value by default.  The user can set this, and
+        // thus engage a timer for this # of milliseconds on each call. If the
+        // timer fires before the call returns, a fault will be generated.
+        timeout = -1;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    private var resourceManager:IResourceManager =
+                                    ResourceManager.getInstance();
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  decoder
+    //----------------------------------
+
+    /**
+     * The ISOAPDecoder implementation used by this Operation to decode a SOAP
+     * encoded response into ActionScript.
+     * 
+     * @private
+     */
+    public function get decoder():ISOAPDecoder
+    {
+        if (_decoder == null)
+        {
+            _decoder = new SOAPDecoder();
+            _decoder.makeObjectsBindable = makeObjectsBindable;
+            _decoder.ignoreWhitespace = ignoreWhitespace;
+        }
+
+        if (_decoder.wsdlOperation == null)
+            _decoder.wsdlOperation = wsdlOperation;
+
+        return _decoder;
+    }
+
+    /**
+     * @private
+     */
+    public function set decoder(value:ISOAPDecoder):void
+    {
+        _decoder = value;
+    }
+
+
+    //----------------------------------
+    //  encoder
+    //----------------------------------
+
+    /**
+     * The ISOAPEncoder implementation used by this Operation to encode
+     * ActionScript input arguments as a SOAP encoded request.
+     * 
+     * @private
+     */
+    public function get encoder():ISOAPEncoder
+    {
+        if (_encoder == null)
+        {
+            _encoder = new SOAPEncoder();
+            _encoder.ignoreWhitespace = ignoreWhitespace;
+        }
+
+        if (_encoder.wsdlOperation == null)
+            _encoder.wsdlOperation = wsdlOperation;
+            
+        // Tell the encoder to use the xmlSpecialCharsFilter function specified
+        // on the Operation (or Service). If null, encoder will default to its
+        // own implementation.
+        _encoder.xmlSpecialCharsFilter = xmlSpecialCharsFilter;
+
+        return _encoder;
+    }
+
+    /**
+     * @private
+     */
+    public function set encoder(value:ISOAPEncoder):void
+    {
+        _encoder = value;
+    }
+
+
+    //----------------------------------
+    //  endpointURI
+    //----------------------------------
+
+    /**
+     * The location of the WebService for this Operation. Normally, the WSDL
+     * specifies the location of the services, but you can set this property to
+     * override that location for the individual Operation.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get endpointURI():String
+    {
+        return _endpointURI ? _endpointURI : webService.endpointURI;
+    }
+
+    public function set endpointURI(uri:String):void
+    {
+        _endpointURI = uri;
+    }
+
+    //----------------------------------
+    //  forcePartArrays
+    //----------------------------------
+
+    [Inspectable(defaultValue="false", category="General")]
+    /**
+     * Determines whether or not a single or empty return value for an output
+     * message part that is defined as an array should be returned as an array
+     * containing one (or zero, respectively) elements. This is applicable for
+     * document/literal "wrapped" web services, where one or more of the elements
+     * that represent individual message parts in the "wrapper" sequence could
+     * have the maxOccurs attribute set with a value greater than 1. This is a
+     * hint that the corresponding part should be treated as an array even if
+     * the response contains zero or one values for that part. Setting
+     * forcePartArrays to true will always create an array for parts defined in
+     * this manner, regardless of the number of values returned. Leaving
+     * forcePartArrays as false will only create arrays if two or more elements
+     * are returned.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get forcePartArrays():Boolean
+    {
+        return _forcePartArrays;
+    }
+
+    public function set forcePartArrays(value:Boolean):void
+    {
+        _forcePartArrays = value;
+    }
+
+    //----------------------------------
+    //  headerFormat
+    //----------------------------------
+
+    [Inspectable(enumeration="object,e4x,xml,E4X,XML", defaultValue="e4x", category="General")]
+    /**
+     * Determines how the SOAP encoded headers are decoded. A value of
+     * <code>object</code> specifies that each header XML node will be decoded
+     * into a SOAPHeader object, and its <code>content</code> property will be
+     * an object structure as specified in the WSDL document. A value of
+     * <code>xml</code> specifies that the XML will be left as XMLNodes. A
+     * value of <code>e4x</code> specifies that the XML will be accessible
+     * using ECMAScript for XML (E4X) expressions.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get headerFormat():String
+    {
+        if (_headerFormat == null)
+            _headerFormat = "e4x";
+
+        return _headerFormat;
+    }
+
+    public function set headerFormat(hf:String):void
+    {
+        if (hf != null)
+            hf = hf.toLowerCase();
+
+        _headerFormat = hf;
+    }
+
+    //----------------------------------
+    //  headers
+    //----------------------------------
+
+    /**
+     * Accessor to an Array of SOAPHeaders that are to be sent on
+     * each invocation of the operation.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get headers():Array
+    {
+        return _headers;
+    }
+
+
+    //----------------------------------
+    //  httpHeaders
+    //----------------------------------
+
+    private var _httpHeaders:Object;
+
+    [Inspectable(defaultValue="undefined", category="General")]
+    /**
+     * Custom HTTP headers to be sent to the SOAP endpoint. If multiple
+     * headers need to be sent with the same name the value should be specified
+     * as an Array.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get httpHeaders():Object
+    {
+        if (_httpHeaders != null)
+            return _httpHeaders;
+
+        return AbstractWebService(service).httpHeaders; 
+    }
+
+    public function set httpHeaders(value:Object):void
+    {
+        _httpHeaders = value;
+    }
+
+
+    //----------------------------------
+    //  ignoreWhitespace
+    //----------------------------------
+
+    [Inspectable(defaultValue="true", category="General")]
+    /**
+     * Determines whether whitespace is ignored when processing XML for a SOAP
+     * encoded request or response. The default is <code>true</code>
+     * and thus whitespace is not preserved. If an XML Schema type definition
+     * specifies a <code>whiteSpace</code> restriction set to
+     * <code>preserve</code> then ignoreWhitespace must first be set to false.
+     * Conversely, if a type <code>whiteSpace</code> restriction is set to
+     * <code>replace</code> or <code>collapse</code> then that setting will
+     * be honored even if ignoreWhitespace is set to false.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get ignoreWhitespace():Boolean
+    {
+        return _ignoreWhitespace;
+    }
+
+    public function set ignoreWhitespace(value:Boolean):void
+    {
+        _ignoreWhitespace = value;
+
+        if (_decoder != null)
+            _decoder.ignoreWhitespace = _ignoreWhitespace;
+
+        if (_encoder != null)
+            _encoder.ignoreWhitespace = _ignoreWhitespace;
+    }
+
+
+    //----------------------------------
+    //  makeObjectsBindable
+    //----------------------------------
+
+    [Inspectable(defaultValue="true", category="General")]
+    /**
+     * When this value is true, anonymous objects returned are forced to
+     * bindable objects.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function get makeObjectsBindable():Boolean
+    {
+        if (_makeObjectsBindableSet)
+        {
+            return _makeObjectsBindable;
+        }
+        return AbstractWebService(service).makeObjectsBindable;    
+    }
+
+    override public function set makeObjectsBindable(value:Boolean):void
+    {
+        _makeObjectsBindable = value;
+        _makeObjectsBindableSet = true;
+
+        if (_decoder != null)
+            _decoder.makeObjectsBindable = value;
+    }
+
+
+    //----------------------------------
+    //  multiplePartsFormat
+    //----------------------------------
+
+    [Inspectable(enumeration="object,array", defaultValue="object", category="General")]
+    /**
+     * Determines the type of the default result object for calls to web services
+     * that define multiple parts in the output message. A value of "object"
+     * specifies that the lastResult object will be an Object with named properties
+     * corresponding to the individual output parts. A value of "array" would
+     * make the lastResult an array, where part values are pushed in the order
+     * they occur in the body of the SOAP message. The default value for document-
+     * literal operations is "object". The default for rpc operations is "array".
+     * The multiplePartsFormat property is applicable only when
+     * resultFormat is "object" and ignored otherwise.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get multiplePartsFormat():String
+    {
+        if (_multiplePartsFormat == null)
+        {
+            // To keep Flex 2.0.1 HF 2+ behavior, we need to determine the
+            // default value based on the style of the operation.
+            if (_wsdlOperation != null && _wsdlOperation.style == "rpc")
+                _multiplePartsFormat = "array";
+            else
+                _multiplePartsFormat = "object";
+        }
+
+        return _multiplePartsFormat;
+    }
+
+    public function set multiplePartsFormat(value:String):void
+    {
+        if (value != null)
+            value = value.toLowerCase();
+
+        _multiplePartsFormat = value;
+    }
+
+    //----------------------------------
+    //  request
+    //----------------------------------
+
+    /**
+     * The request of the Operation is an object structure or an XML structure.
+     * If you specify XML, the XML is sent as is. If you pass an object, it is
+     * encoded into a SOAP XML structure.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get request():Object
+    {
+        return this.arguments;
+    }
+
+    public function set request(r:Object):void
+    {
+        this.arguments = r;
+    }
+
+
+    //----------------------------------
+    //  resultFormat
+    //----------------------------------
+
+    [Inspectable(enumeration="object,e4x,xml,E4X,XML", defaultValue="object", category="General")]
+    /**
+     * Determines how the Operation result is decoded. A value of
+     * <code>object</code> specifies that the XML will be decoded into an
+     * object structure as specified in the WSDL document. A value of
+     * <code>xml</code> specifies that the XML will be left as XMLNodes. A
+     * value of <code>e4x</code> specifies that the XML will be accessible
+     * using ECMAScript for XML (E4X) expressions.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get resultFormat():String
+    {
+        if (_resultFormat == null)
+            _resultFormat = "object";
+
+        return _resultFormat;
+    }
+
+    public function set resultFormat(rf:String):void
+    {
+        if (rf != null)
+            rf = rf.toLowerCase();
+
+        _resultFormat = rf;
+    }
+
+
+    //----------------------------------
+    //  resultHeaders
+    //----------------------------------
+
+    [Bindable("resultForBinding")]
+    /**
+     * The headers that were returned as part of the last execution of this
+     * operation. They match up with the <code>lastResult</code> property and
+     * are the same as the collection of headers that are dispatched
+     * individually as HeaderEvents.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get resultHeaders():Array
+    {
+        return _responseHeaders;
+    }
+
+
+    //----------------------------------
+    //  xmlSpecialCharsFilter
+    //----------------------------------
+
+    private var _xmlSpecialCharsFilter:Function;
+
+    /**
+     *  Specifies a custom function used to escape XML special characters before 
+     *  encoding any simple content. 
+     *  Valid for all operations on the web service unless specifically overwritten 
+     *  on the operation level. 
+     *  If no function is provided, the defaults is whatever is set by the 
+     *  particular implementation of IXMLEncoder.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get xmlSpecialCharsFilter():Function
+    {
+        if (_xmlSpecialCharsFilter != null)
+            return _xmlSpecialCharsFilter;
+
+        return AbstractWebService(service).xmlSpecialCharsFilter;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set xmlSpecialCharsFilter(func:Function):void
+    {
+        _xmlSpecialCharsFilter = func;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Internal Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * @private
+     */
+    mx_internal var handleAxisSession:Boolean;
+
+    /**
+     * @private
+     */
+    mx_internal function get wsdlOperation():WSDLOperation
+    {
+        return _wsdlOperation;
+    }
+
+    /**
+     * @private
+     */
+    mx_internal function set wsdlOperation(value:WSDLOperation):void
+    {
+        _wsdlOperation = value;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Adds a header that is applied only to this Operation. The header can be
+     * provided in a pre-encoded form as an XML instance, or as a SOAPHeader
+     * instance which leaves the encoding up to the internal SOAP encoder.
+     * @param header The SOAP header to add to this Operation.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function addHeader(header:Object):void
+    {
+        _headers.push(header);
+    }
+
+    /**
+     * Adds a header that is applied only to this Operation.
+     * @param qnameLocal the localname for the header QName
+     * @param qnameNamespace the namespace for header QName
+     * @param headerName Name of the header.
+     * @param headerValue Value of the header.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function addSimpleHeader(qnameLocal:String, qnameNamespace:String,
+            headerName:String, headerValue:String):void
+    {
+        var obj:Object = {};
+        obj[headerName] = headerValue;
+        addHeader(new SOAPHeader(new QName(qnameNamespace, qnameLocal), obj));
+    }
+
+    /**
+     * @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function cancel(id:String = null):AsyncToken
+    {
+        
+        if (hasPendingInvocations())
+        {
+            if (null == id)
+            {
+                // remove the last pending call
+                return pendingInvocations.pop().token;
+            }
+            // check if id is one of the pending calls
+            for (var i:int = pendingInvocations.length-1; i >= 0; i--)
+            {
+                if (pendingInvocations[i].token.message != null &&
+                    pendingInvocations[i].token.message.messageId == id)
+                {
+                    var pc:OperationPendingCall = pendingInvocations.splice(i,1)[0];
+                    return pc.token;
+                }
+            }
+        }
+        //if the call is not pending, use super
+        return super.cancel(id);
+    }
+
+    /**
+     * Clears the headers for this individual Operation.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function clearHeaders():void
+    {
+        _headers.length = 0;
+    }
+
+    /**
+     * Returns a header if a match is found based on QName localName and URI.
+     * @param qname QName of the SOAPHeader.
+     * @param headerName Name of a header in the SOAPHeader content (Optional)
+     * @return Returns the SOAPHeader.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function getHeader(qname:QName, headerName:String = null):SOAPHeader
+    {
+        var length:uint = _headers.length;
+        for (var i:uint = 0; i < length; i++)
+        {
+            var header:SOAPHeader = SOAPHeader(_headers[i]);
+            if (XMLUtil.qnamesEqual(header.qname, qname))
+            {
+                if (headerName)
+                {
+                    if (header.content && header.content[headerName])
+                    {
+                        return header;
+                    }
+                }
+                else
+                {
+                    return header;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Removes the header with the given QName from all operations.
+     * @param qname QName of the SOAPHeader.
+     * @param headerName Name of a header in the SOAPHeader content (Optional)
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function removeHeader(qname:QName, headerName:String = null):void
+    {
+        var length:uint = _headers.length;
+        for (var i:uint = 0; i < length; i++)
+        {
+            var header:SOAPHeader = SOAPHeader(_headers[i]);
+            if (XMLUtil.qnamesEqual(header.qname, qname))
+            {
+                if (headerName)
+                {
+                    if (header.content && header.content[headerName])
+                    {
+                        _headers.splice(i, 1);
+                        return; // Got it
+                    }
+                }
+                else
+                {
+                    _headers.splice(i, 1);
+                    return; // Got it
+                }
+            }
+        }
+    }
+
+    /**
+     * @private
+     */
+    override public function send(...args:Array):AsyncToken
+    {
+        if (service != null)
+            service.initialize();
+
+        if (webService.convertParametersHandler != null)
+            args = webService.convertParametersHandler(args);
+
+        if (operationManager != null)
+            return operationManager(args);
+
+        var argsToPass:Object = null;
+        if (args && args.length > 0)
+        {
+            if ((args.length == 1) && (args[0] is XMLNode || args[0] is XML))
+            {
+                // special case: handle xml node as single argument and drop
+                // into literal mode.
+                argsToPass = args[0];
+            }
+            else
+            {
+                argsToPass = args;
+            }
+        }
+        //Syntactically pre-registered
+        else if (this.arguments)
+        {
+            argsToPass = this.arguments;
+        }
+
+        var combinedHeaders:Array = [];
+
+        if (_headers)
+        {
+            combinedHeaders = combinedHeaders.concat(_headers);
+        }
+
+        if (webService.headers)
+        {
+            combinedHeaders = combinedHeaders.concat(webService.headers);
+        }
+
+        //create an empty message and a token to hold it
+        var message:SOAPMessage = new SOAPMessage();
+        var token:AsyncToken = new AsyncToken(message);
+        
+        var pc:OperationPendingCall = new OperationPendingCall(argsToPass, combinedHeaders, token);
+
+        if (webService.ready)
+        {
+            invokePendingCall(pc);
+        }
+        else // if (!webService.wsdlFault)
+        {
+            log.debug("Queueing SOAP operation {0}", name);
+            if (!pendingInvocations)
+            {
+                pendingInvocations = [];
+            }
+            pendingInvocations.push(pc);
+        }
+        // FIXME: Handle WSDL error case
+        /*
+        else
+        {
+            var errMsg:String = "Cannot invoke method " + name + " as WSDL did not load successfully";
+            dispatchRpcEvent(createFaultEvent("Client.InvalidWSDL", errMsg));
+        }
+        */
+
+        return pc.token;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Internal Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * @private
+     */
+    mx_internal function hasPendingInvocations():Boolean
+    {
+        return pendingInvocations != null && pendingInvocations.length > 0;
+    }
+
+    /**
+     * @private
+     */
+    mx_internal function invokeAllPending():void
+    {
+        if (hasPendingInvocations())
+        {
+            for (var i:int = 0; i < pendingInvocations.length; ++i)
+            {
+                invokePendingCall(pendingInvocations[i]);
+            }
+            pendingInvocations = null;
+        }
+    }
+
+    /**
+     * We now SOAP encode the pending call and send the request.
+     * 
+     * @private
+     */
+    mx_internal function invokePendingCall(pc:OperationPendingCall):void
+    {
+        log.debug("Invoking SOAP operation {0}", name);
+
+        startTime = new Date();
+
+        var message:SOAPMessage = SOAPMessage(pc.token.message);
+        var soap:XML;
+
+        if (wsdlOperation == null)
+        {
+            log.debug("No operation found {0}", name);
+            dispatchRpcEvent(createFaultEvent("Client.NoSuchMethod", "Couldn't find method '" + name + "' in service."));
+            return;
+        }
+
+        try
+        {
+            soap = encoder.encodeRequest(pc.args, pc.headers);
+        }
+        catch(fault:Fault)
+        {
+            dispatchRpcEvent(FaultEvent.createEvent(fault));
+            return;
+        }
+        catch(error:Error)
+        {
+            var errorMsg:String = error.message ? error.message : "";
+            var fault2:Fault = new Fault("EncodingError", errorMsg);
+            var faultEvent:FaultEvent = FaultEvent.createEvent(fault2);
+            dispatchRpcEvent(faultEvent);
+            return;
+        }
+
+        message.httpHeaders = httpHeaders;
+        if (message.getSOAPAction() == null)
+            message.setSOAPAction(wsdlOperation.soapAction);
+        message.body = soap.toXMLString();
+        message.url = endpointURI;
+        if (NetworkMonitor.isMonitoring())
+        {
+            message.recordHeaders = true;    
+        }
+
+        invoke(message, pc.token);
+    }
+
+    /**
+     * We intercept faults as the SOAP response content may still been present
+     * in the message body.
+     *
+     * @private
+     */
+    override mx_internal function processFault(message:IMessage, token:AsyncToken):Boolean
+    {
+        var dispatchFaultEvent:Boolean = true;
+
+        if (message != null && message.body != null)
+        {
+            dispatchFaultEvent = processSOAP(message, token);
+        }
+
+        return dispatchFaultEvent;
+    }
+
+    /**
+     * We decode the SOAP encoded response and update the result and response
+     * headers (if any).
+     * 
+     * @private
+     */
+    override mx_internal function processResult(message:IMessage, token:AsyncToken):Boolean
+    {
+        if (processSOAP(message, token))
+        {
+            if (webService.convertResultHandler != null)
+                _result = webService.convertResultHandler(_result, this);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @private
+     */ 
+    mx_internal function processSOAP(message:IMessage, token:AsyncToken):Boolean
+    {
+        var body:Object = message.body;
+        var eventDispatchRequired:Boolean = true;
+
+        try
+        {
+            var stringResult:String = String(body);
+            decoder.resultFormat = resultFormat;
+            decoder.headerFormat = headerFormat;
+            decoder.multiplePartsFormat = multiplePartsFormat;
+            decoder.forcePartArrays = forcePartArrays;
+
+            var soapResult:SOAPResult = decoder.decodeResponse(stringResult);
+
+            // Reset result
+            _result = null;
+
+            // Expose headers for the bindable property "resultHeaders" as
+            // well as RPC fault and result events...
+            _responseHeaders = soapResult.headers;
+
+            // Process headers for both result and fault
+            eventDispatchRequired = processHeaders(_responseHeaders, token, message);
+
+            // Handle faults
+            if (soapResult.isFault)
+            {
+                var faults:Array = soapResult.result as Array;
+                for each (var soapFault:Fault in faults)
+                {
+                    soapFault.content = body;
+                    dispatchRpcEvent(FaultEvent.createEvent(soapFault, token, message));
+                }
+                eventDispatchRequired = false;
+            }
+
+            if (eventDispatchRequired)
+                _result = soapResult.result;
+        }
+        catch (fault:Fault)
+        {
+            fault.content = body;
+            dispatchRpcEvent(FaultEvent.createEvent(fault, token, message));
+            eventDispatchRequired = false;
+        }
+        catch (error:Error)
+        {
+            var errorMsg:String = error.message != null ? error.message : "";
+            var fault2:Fault = new Fault("DecodingError", errorMsg);
+            fault2.content = body;
+            var faultEvent:FaultEvent = FaultEvent.createEvent(fault2, token, message);
+            dispatchRpcEvent(faultEvent);
+            eventDispatchRequired = false;
+        }
+
+        return eventDispatchRequired;
+    }
+
+    /**
+     * Checks SOAP response headers and enforces any mustUnderstand attributes
+     * by checking that a listener exists for the "header" event. If we're
+     * honoring Axis sessions then we also look out for for the sessionID
+     * header and add it to the Operation's corresponding service for
+     * subsequent invocations. Finally, the header is dispatched as a
+     * HeaderEvent. If no problems are encountered the method simply returns
+     * true.
+     * 
+     * @private
+     */
+    protected function processHeaders(responseHeaders:Array, token:AsyncToken, message:IMessage):Boolean
+    {
+        if (responseHeaders != null)
+        {
+            for (var i:uint = 0; i < responseHeaders.length; i++)
+            {
+                var header:Object = responseHeaders[i];
+                var mustUnderstand:Boolean;
+                var headerQName:QName;
+                var headerContent:Object;
+
+                if (header is XML)
+                {
+                    var headerXML:XML = header as XML;
+
+                    mustUnderstand = headerXML.@mustUnderstand == "1" ? true : false;
+                    headerQName = headerXML.name() as QName;
+
+                    if (headerXML.hasComplexContent())
+                        headerContent = headerXML.elements();
+                    else
+                        headerContent = headerXML.text();
+
+                }
+                else if (header is SOAPHeader)
+                {
+                    mustUnderstand = header.mustUnderstand;
+                    headerQName = header.qname;
+                    headerContent = header.content;
+                }
+
+                // If header was either XML or SOAPHeader, headerQName would
+                // be set by now.
+                if (headerQName != null)
+                {
+                    if (mustUnderstand == true)
+                    {
+                        if (!hasEventListener(HeaderEvent.HEADER) && !service.hasEventListener(HeaderEvent.HEADER))
+                        {
+                            var msg:String = resourceManager.getString(
+                                "rpc", "noListenerForHeader",
+                                [ headerQName ]);
+                            var fault:Fault = new Fault("Client.MustUnderstand", msg);
+                            var faultEvent:FaultEvent = FaultEvent.createEvent(fault, token, message);
+                            dispatchRpcEvent(faultEvent);
+                            return false;
+                        }
+                    }
+
+                    if (handleAxisSession)
+                    {
+                        // pass the session id on to any request made on this proxy
+                        if (headerQName != null && headerQName.localName == "sessionID" &&
+                            headerQName.uri == "http://xml.apache.org/axis/session")
+                        {
+                            var newHeader:SOAPHeader = new SOAPHeader(headerQName, headerContent);
+                            webService.addHeader(newHeader);
+                        }
+                    }
+
+                    var headerEvent:HeaderEvent = HeaderEvent.createEvent(header, token, message);
+                    dispatchRpcEvent(headerEvent);
+                }
+            }
+        }
+
+        return true; 
+    }
+
+    /**
+     * @private
+     */
+    override mx_internal function setService(value:AbstractService):void
+    {
+        super.setService(value);
+        webService = AbstractWebService(value);
+    }
+
+    /**
+     * @private
+     */
+    protected function createFaultEvent(faultCode:String = null, faultString:String = null, faultDetail:String = null):FaultEvent
+    {
+        var fault:Fault = new Fault(faultCode, faultString, faultDetail);
+        var faultEvent:FaultEvent = FaultEvent.createEvent(fault);
+        return faultEvent;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    // Backing variables for public getter/setters
+    private var _endpointURI:String;
+    private var _forcePartArrays:Boolean = false; // Flex 2.0.1 HF2+ behavior is false
+    private var _headerFormat:String;
+    private var _headers:Array;
+    private var _resultFormat:String;
+    private var _makeObjectsBindableSet:Boolean;
+    private var _multiplePartsFormat:String;
+
+    // Internal properties
+    //any vars here with underscores minimally have a getter or setter
+    private var _decoder:ISOAPDecoder;
+    private var _encoder:ISOAPEncoder;
+    private var _ignoreWhitespace:Boolean = true;
+    private var log:ILogger;
+    private var pendingInvocations:Array;
+    private var startTime:Date;
+    private var timeout:int;
+    private var webService:AbstractWebService;
+
+    /**
+     * @private
+     */
+    protected var _wsdlOperation:mx.rpc.wsdl.WSDLOperation;
+}
+}
+
+import mx.rpc.AsyncToken;
+
+/**
+ * @private
+ */
+class OperationPendingCall
+{
+    public var args:*;
+    public var headers:Array;
+    public var token:AsyncToken;
+
+    public function OperationPendingCall(args:*, headers:Array, token:AsyncToken)
+    {
+        super();
+        this.args = args;
+        this.headers = headers;
+        this.token = token;
+    }
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPConstants.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPConstants.as
new file mode 100644
index 0000000..b509e71
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPConstants.as
@@ -0,0 +1,351 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+import org.apache.royale.reflection.getDefinitionByName;
+import org.apache.royale.reflection.getQualifiedClassName;
+
+import mx.rpc.soap.types.ICustomSOAPType;
+import mx.rpc.soap.types.MapType;
+import mx.rpc.soap.types.QueryBeanType;
+import mx.rpc.soap.types.RowSetType;
+import mx.rpc.soap.types.SOAPArrayType;
+import mx.rpc.soap.types.ApacheDocumentType;
+import mx.rpc.soap.types.DataSetType;
+import mx.utils.StringUtil;
+import mx.utils.URLUtil;
+
+[ExcludeClass]
+
+/**
+ * A helper class listing all of the constants required to encode and decode
+ * SOAP messages.
+ * 
+ * @private
+ */
+public class SOAPConstants
+{
+    public function SOAPConstants(envelopeNS:Namespace = null, encodingNS:Namespace = null)
+    {
+        super();
+
+        // Default to SOAP 1.1
+        if (envelopeNS == null)
+            envelopeNS = new Namespace(SOAP_ENV_PREFIX, SOAP_ENVELOPE_URI);
+
+        if (encodingNS == null)
+            encodingNS = new Namespace(SOAP_ENC_PREFIX, SOAP_ENCODING_URI);
+
+        _envelopeNS = envelopeNS;
+        _encodingNS = encodingNS;
+
+        envelopeQName = new QName(envelopeURI, "Envelope");
+        headerQName = new QName(envelopeURI, "Header");
+        bodyQName = new QName(envelopeURI, "Body");
+        faultQName = new QName(envelopeURI, "Fault");
+        actorQName = new QName(envelopeURI, "actor");
+        mustUnderstandQName = new QName(envelopeURI, "mustUnderstand");
+
+        soapencArrayQName = new QName(encodingURI, "Array");
+        soapencArrayTypeQName = new QName(encodingURI, "arrayType");
+        soapencRefQName = new QName(encodingURI, "multiRef");
+        soapoffsetQName = new QName(encodingURI, "offset");
+        soapBase64QName = new QName(encodingURI, "base64");
+
+        // Initialize custom SOAP type handlers
+        if (!customTypesInitialized)
+            initCustomSOAPTypes();
+        
+        // Register Types with version-specific QNames
+        registerCustomSOAPType(soapencArrayQName, SOAPArrayType);
+        registerCustomSOAPType(soapencArrayTypeQName, SOAPArrayType);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+    
+    public function get contentType():String
+    {
+        return _contentType;
+    }
+
+    public function get encodingURI():String
+    {
+        return encodingNamespace.uri;
+    }
+
+    public function get encodingNamespace():Namespace
+    {
+        return _encodingNS;
+    }
+    
+    public function get envelopeURI():String
+    {
+        return envelopeNamespace.uri;
+    }
+
+    public function get envelopeNamespace():Namespace
+    {
+        return _envelopeNS;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    public function getSOAPEncodingToken(type:QName):String
+    {
+        return encodingNamespace.prefix + ":" + type.localName;
+    }
+
+    public static function getConstants(xml:XML = null):SOAPConstants
+    {
+        var envelopeNS:Namespace;
+        var encodingNS:Namespace;
+
+        if (xml != null)
+        {
+            var nsArray:Array = xml.namespaceDeclarations();
+            for each (var ns:Namespace in nsArray)
+            {
+                if (URLUtil.urisEqual(ns.uri, SOAP_ENVELOPE_URI)
+                    || URLUtil.urisEqual(ns.uri, SOAP12_ENVELOPE_URI))
+                {
+                    envelopeNS = ns;
+                }
+                else if (URLUtil.urisEqual(ns.uri, SOAP_ENCODING_URI)
+                    || URLUtil.urisEqual(ns.uri, SOAP12_ENCODING_URI))
+                {
+                    encodingNS = ns;
+                }
+            }
+        }
+
+        // Default to SOAP 1.1
+        if (envelopeNS == null)
+            envelopeNS = new Namespace(SOAP_ENV_PREFIX, SOAP_ENVELOPE_URI);
+
+        if (encodingNS == null)
+            encodingNS = new Namespace(SOAP_ENC_PREFIX, SOAP_ENCODING_URI);
+
+        if (constantsCache == null)
+            constantsCache = {};
+
+        var constants:SOAPConstants = constantsCache[envelopeNS.uri];
+        if (constants == null)
+        {
+            constants = new SOAPConstants(envelopeNS, encodingNS);
+            constantsCache[envelopeNS.uri] = constants;
+        }
+
+        return constants;
+    }
+
+    public static function isSOAPEncodedType(type:QName):Boolean
+    {
+        var uri:String = (type != null) ? type.uri : null;
+        if (uri != null)
+        {
+            if (URLUtil.urisEqual(uri, SOAPConstants.SOAP_ENCODING_URI) ||
+                URLUtil.urisEqual(uri, SOAPConstants.SOAP12_ENCODING_URI))
+            {
+                return true;    
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Looks for an ICustomSOAPType implementation for the given type. 
+     * 
+     * @return A new instance of the ICustomSOAPType, if registered, otherwise
+     * null.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function getCustomSOAPType(type:QName):ICustomSOAPType
+    {
+        var soapType:ICustomSOAPType;
+        if (type != null)
+        {
+            var key:String = getKey(type);
+            var definitionName:String = typeMap[key] as String;
+
+            if (definitionName != null)
+            {
+                try
+                {
+                    var c:Class = getDefinitionByName(definitionName) as Class;
+                    soapType = new c() as ICustomSOAPType;
+                }
+                catch(e:Error)
+                {
+                }
+            }
+        }
+        return soapType;
+    }
+
+    /**
+     * Maps a type QName to a definition of an ISOAPType implementation.
+     * The definition can be a String representation of the fully qualified
+     * class name, an Object instance or the Class instance itself.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function registerCustomSOAPType(type:QName, definition:*):void
+    {
+        var key:String = getKey(type);
+
+        var definitionName:String;
+
+        if (definition is String)
+            definitionName = definition as String;
+        else
+            definitionName = getQualifiedClassName(definition);
+
+        typeMap[key] = definitionName;
+    }
+
+    /**
+     * Removes the ICustomSOAPType from the registry for the given type.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function unregisterCustomSOAPType(type:QName):void
+    {
+        if (type != null)
+        {
+            var key:String = getKey(type);
+            delete typeMap[key];
+        }
+    }
+
+    private static function getKey(type:QName):String
+    {
+        var key:String;
+        if (type.uri == null || type.uri == "")
+            key = type.localName;
+        else
+            key = type.toString();
+        return key;
+    }
+
+    private static function initCustomSOAPTypes():void
+    {
+        registerCustomSOAPType(queryBeanQName, QueryBeanType);
+        registerCustomSOAPType(mapQName, MapType);
+        registerCustomSOAPType(rowSetQName, RowSetType);
+        registerCustomSOAPType(documentQName, ApacheDocumentType);
+        registerCustomSOAPType(diffgramQName, DataSetType);
+        customTypesInitialized = true;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+    
+    // SOAP Envelope QNames
+    public var envelopeQName:QName;
+    public var headerQName:QName;
+    public var bodyQName:QName;
+    public var faultQName:QName;
+    public var actorQName:QName;
+    public var mustUnderstandQName:QName;
+
+    // SOAP Encoding QNames
+    public var soapencArrayQName:QName;
+    public var soapencArrayTypeQName:QName;
+    public var soapencRefQName:QName;
+    public var soapoffsetQName:QName;
+    public var soapBase64QName:QName;
+
+    private var _contentType:String;
+    private var _envelopeNS:Namespace;
+    private var _encodingNS:Namespace;
+
+    private static var constantsCache:Object;
+    private static var customTypesInitialized:Boolean;
+    private static var typeMap:Object = {};
+
+    //--------------------------------------------------------------------------
+    //
+    // Constants
+    // 
+    //--------------------------------------------------------------------------
+
+    // ColdFusion SOAP Type QNames
+    public static const queryBeanQName:QName = new QName(COLD_FUSION_URI, "QueryBean");
+
+    // Apache SOAP Type QNames
+    public static const rowSetQName:QName = new QName(APACHE_SOAP_URI, "RowSet");
+    public static const mapQName:QName = new QName(APACHE_SOAP_URI, "Map");
+    public static const documentQName:QName = new QName(APACHE_SOAP_URI, "Document");
+    
+    // MS .NET DataSet Constants
+    public static const msdataURI:String = "urn:schemas-microsoft-com:xml-msdata";
+    public static const diffgramQName:QName = new QName("urn:schemas-microsoft-com:xml-diffgram-v1", "diffgram");
+
+    // SOAP Envelope Constants
+    public static const SOAP_ENVELOPE_URI:String = "http://schemas.xmlsoap.org/soap/envelope/";
+    public static const SOAP12_ENVELOPE_URI:String = "http://www.w3.org/2002/12/soap-envelope";
+    public static const XML_DECLARATION:String = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+
+    // SOAP Encoding Constants
+    public static const SOAP_ENCODING_URI:String = "http://schemas.xmlsoap.org/soap/encoding/";
+    public static const SOAP12_ENCODING_URI:String = "http://www.w3.org/2002/12/soap-encoding";
+    public static const SOAP_CONTENT_TYPE:String = "text/xml; charset=utf-8";
+    public static const SOAP12_CONTENT_TYPE:String = "application/soap+xml; charset=utf-8";    
+
+    public static const RPC_STYLE:String = "rpc";
+    public static const DOC_STYLE:String = "document";
+    public static const WRAPPED_STYLE:String = "wrapped";
+    public static const USE_ENCODED:String = "encoded";
+    public static const USE_LITERAL:String = "literal";
+    public static const DEFAULT_OPERATION_STYLE:String = "document";
+    public static const DEFAULT_USE:String = "literal";
+
+    // Default namespace prefixes
+    public static const SOAP_ENV_PREFIX:String = "SOAP-ENV";
+    public static const SOAP_ENC_PREFIX:String = "SOAP-ENC";
+
+    // Custom SOAP Type Constants
+    public static const COLD_FUSION_URI:String   = "http://rpc.xml.coldfusion";
+    public static const APACHE_SOAP_URI:String   = "http://xml.apache.org/xml-soap";
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPDecoder.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPDecoder.as
new file mode 100644
index 0000000..77aa7f6
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPDecoder.as
@@ -0,0 +1,1031 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+import flash.utils.getTimer;
+import flash.xml.XMLDocument;
+import flash.xml.XMLNode;
+
+import mx.logging.ILogger;
+import mx.logging.Log;
+import mx.rpc.soap.types.ICustomSOAPType;
+import mx.rpc.wsdl.WSDLEncoding;
+import mx.rpc.wsdl.WSDLMessagePart;
+import mx.rpc.wsdl.WSDLOperation;
+import mx.rpc.xml.ContentProxy;
+import mx.rpc.xml.DecodingContext;
+import mx.rpc.xml.SchemaConstants;
+import mx.rpc.xml.SchemaDatatypes;
+import mx.rpc.xml.TypeIterator;
+import mx.rpc.xml.XMLDecoder;
+import mx.utils.StringUtil;
+import mx.utils.URLUtil;
+import mx.utils.XMLUtil;
+import mx.utils.object_proxy;
+
+use namespace object_proxy;
+
+[ExcludeClass]
+
+/**
+ * Decodes the SOAP response for a particular operation
+ * 
+ * @private
+ */
+public class SOAPDecoder extends XMLDecoder implements ISOAPDecoder
+{
+    //--------------------------------------------------------------------------
+    //
+    // Constructor
+    // 
+    //--------------------------------------------------------------------------
+
+    public function SOAPDecoder()
+    {
+        super();
+        log = Log.getLogger("mx.rpc.soap.SOAPDecoder");
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Controls whether the decoder supports the legacy literal style encoding
+     * for generic compound type (such as arrays). Older document-literal SOAP
+     * implementations sometimes encoded unbounded element sequences with
+     * generic child <code>item</code> elements instead of repeating the
+     * value element itself. The default is true.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var supportGenericCompoundTypes:Boolean = false;
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    public function get forcePartArrays():Boolean
+    {
+        return _forcePartArrays;
+    }
+
+    public function set forcePartArrays(value:Boolean):void
+    {
+        _forcePartArrays = value;
+    }
+
+    public function get headerFormat():String
+    {
+        return _headerFormat;
+    }
+
+    public function set headerFormat(value:String):void
+    {
+        _headerFormat = value;
+    }
+
+    /**
+     * Determines whether the decoder should ignore whitespace when processing
+     * the XML of a SOAP encoded response. The default is <code>true</code>
+     * and thus whitespace is not preserved. If an XML Schema type definition
+     * specifies a <code>whiteSpace</code> restriction set to
+     * <code>preserve</code> then ignoreWhitespace must first be set to false.
+     * Conversely, if a type <code>whiteSpace</code> restriction is set to
+     * <code>replace</code> or <code>collapse</code> then that setting will
+     * be honored even if ignoreWhitespace is set to false.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get ignoreWhitespace():Boolean
+    {
+        return _ignoreWhitespace;
+    }
+
+    public function set ignoreWhitespace(value:Boolean):void
+    {
+        _ignoreWhitespace = value;
+    }
+
+    public function get multiplePartsFormat():String
+    {
+        return _multiplePartsFormat;
+    }
+    
+    public function set multiplePartsFormat(value:String):void
+    {
+        _multiplePartsFormat = value;
+    }
+
+    public function get resultFormat():String
+    {
+        return _resultFormat;
+    }
+
+    public function set resultFormat(value:String):void
+    {
+        _resultFormat = value;
+    }
+
+    public function get schemaConstants():SchemaConstants
+    {
+        return schemaManager.schemaConstants;
+    }
+
+    public function get soapConstants():SOAPConstants
+    {
+        return wsdlOperation.soapConstants;
+    }
+
+    public function get wsdlOperation():WSDLOperation
+    {
+        return _wsdlOperation;
+    }
+
+    public function set wsdlOperation(value:WSDLOperation):void
+    {
+        _wsdlOperation = value;
+        schemaManager = _wsdlOperation.schemaManager;
+    }
+
+    /**
+     * @private
+     */
+    protected function get inputEncoding():WSDLEncoding
+    {
+        var encoding:WSDLEncoding;
+        if (_wsdlOperation.inputMessage != null)
+            encoding = _wsdlOperation.inputMessage.encoding;
+        else
+            encoding = new WSDLEncoding();
+        return encoding;
+    }
+
+    /**
+     * @private
+     */
+    protected function get outputEncoding():WSDLEncoding
+    {
+        var encoding:WSDLEncoding;
+        if (_wsdlOperation.outputMessage != null)
+            encoding = _wsdlOperation.outputMessage.encoding;
+        else
+            encoding = new WSDLEncoding();
+        return encoding;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods - SOAP Decoding
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Decodes a SOAP response into a result and headers. 
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function decodeResponse(response:*):SOAPResult
+    {
+        var soapResult:SOAPResult;
+        var responseString:String;
+
+        if (response is XML)
+            responseString = XML(response).toXMLString(); 
+        else
+            responseString = String(response);
+
+        var startTime:int = getTimer();
+
+        log.info("Decoding SOAP response");
+
+        // Reset the decoder state to clear contexts for schema types, etc.
+        reset();
+
+        if (responseString != null)
+        {
+            log.debug("Encoded SOAP response {0}", responseString);
+
+            // Keep track of the previous ignoreWhitespace setting (as it is
+            // unfortunately a static API on the intrinsic XML type) so we
+            // can set it back to its original state once we're finished.
+            var oldIgnoreWhitespace:Boolean = XML.ignoreWhitespace;
+            try
+            {
+                // Work around Flash Player bug 192355 by removing whitespace
+                // between processing instructions and the root tag before
+                // constructing an XML instance of the SOAP response.
+                responseString = responseString.replace(PI_WHITESPACE_PATTERN, "?><");
+                responseString = StringUtil.trim(responseString);
+                XML.ignoreWhitespace = ignoreWhitespace;
+                var responseXML:XML = new XML(responseString);
+
+                soapResult = decodeEnvelope(responseXML);
+            }
+            finally
+            {
+                XML.ignoreWhitespace = oldIgnoreWhitespace;
+            }
+        }
+
+        log.info("Decoded SOAP response into result [{0} millis]", getTimer() - startTime);
+        return soapResult;
+    }
+
+    protected function decodeEnvelope(responseXML:XML):SOAPResult
+    {
+        log.debug("Decoding SOAP response envelope");
+        var soapResult:SOAPResult = new SOAPResult();
+
+        var envNS:Namespace;
+
+        if (responseXML != null)
+        {    
+            envNS = responseXML.namespace();
+        }
+
+        if (envNS == null)
+        {
+            throw new Error("SOAP Response cannot be decoded. Raw response: " + responseXML);
+        }
+        else if (envNS.uri != SOAPConstants.SOAP_ENVELOPE_URI)
+        {
+            throw new Error("SOAP Response Version Mismatch");
+        }
+        else
+        {
+            // Set the namespaces and the Schema uri for the decoder.
+            var schemaConst:SchemaConstants;
+            var nsArray:Array = responseXML.inScopeNamespaces();
+            for each (var ns:Namespace in nsArray)
+            {
+                schemaManager.namespaces[ns.prefix] = ns;
+            }
+
+            // SOAP Headers
+            var headerXML:XML = responseXML[soapConstants.headerQName][0];
+            if (headerXML != null)
+            {
+                soapResult.headers = decodeHeaders(headerXML);
+            }
+            // SOAP Body
+            var bodyXML:XML = responseXML[soapConstants.bodyQName][0];
+            
+            if (bodyXML == null || bodyXML.hasComplexContent() == false || bodyXML.children().length() <= 0)
+            {
+                soapResult.result = undefined;
+            }
+            else 
+            {
+                // Check for SOAP faults for all resultFormats
+                var faultXMLList:XMLList = bodyXML[soapConstants.faultQName];
+                if (faultXMLList.length() > 0)
+                {
+                    soapResult.isFault = true;
+                    soapResult.result = decodeFaults(faultXMLList);
+                }
+                else
+                {
+                    if (resultFormat == "object")
+                    {
+                        decodeBody(bodyXML, soapResult);
+                    }
+                    else if (resultFormat == "e4x")
+                    {
+                         // Return the children as an XMLList.
+                        soapResult.result = bodyXML.children();
+                    }
+                    else if (resultFormat == "xml")
+                    {
+                         // Return the children as an Array of XMLNode
+                         // or String for text children
+                        var bodyArray:Array = [];
+                        var bodyXMLList:XMLList = bodyXML.children();
+                        for each (var bodyChild:XML in bodyXMLList)
+                        {
+                            var nodeKind:String = bodyChild.nodeKind();
+                            if (nodeKind == "element")
+                            {
+                                var xmlDoc:XMLDocument = new XMLDocument(bodyChild.toString());
+                                var xmlNode:XMLNode = xmlDoc.firstChild;
+                                bodyArray.push(xmlNode);
+                            }
+                            else if (nodeKind == "text")
+                            {
+                                bodyArray.push(bodyChild.toString());
+                            }
+                        }
+                        soapResult.result = bodyArray;
+                    }
+                }
+            }
+        }
+
+        return soapResult;
+    }
+
+    /**
+     * Decodes the response SOAP Body. The contents may either be the encoded
+     * output parameters, or a collection of SOAP faults.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function decodeBody(bodyXML:XML, soapResult:SOAPResult):void
+    {
+        log.debug("Decoding SOAP response body");
+        var result:*;
+        document = bodyXML;
+
+        // Pre-process encoded body.
+        preProcessXML(bodyXML);
+
+        // Check for operations without an output message
+        if (wsdlOperation.outputMessage == null)
+        {
+            soapResult.result = undefined;
+            return;
+        }
+
+        // Decode WSDL output message parts  
+        var parts:Array = wsdlOperation.outputMessage.parts;
+
+        // Check for operations with a void return type
+        if (parts == null || parts.length == 0)
+        {
+            soapResult.result = undefined;
+            return;
+        }
+
+        var outputMessageXML:XML = bodyXML;
+        if (wsdlOperation.style == SOAPConstants.RPC_STYLE)
+        {
+            // Unwrap the output message from the operation; both RPC encoded and literal wrap.
+            outputMessageXML = outputMessageXML.elements()[0];
+        }
+        else if (outputEncoding.useStyle == SOAPConstants.USE_LITERAL && wsdlOperation.outputMessage.isWrapped == true)
+        {
+            // Get the outputMessage definition and (more importantly) move
+            // down a level into the schema stack.
+            var wrappedDefinition:XML = schemaManager.getNamedDefinition(wsdlOperation.outputMessage.wrappedQName,
+                                                  constants.complexTypeQName,
+                                                  constants.elementTypeQName);
+
+            // TODO: Ensure that throwing this error doesn't break compatibility
+            // if (wrappedDefinition == null)
+            //    throw new Error("Cannot find definition for wrapped response type '" + wsdlOperation.outputMessage.wrappedQName + "'");
+
+            // Unwrap the output message only if this is wrapped literal.
+            outputMessageXML = outputMessageXML.elements()[0];
+        }
+
+        // The "literal" use style may define a part using a type or
+        // element, the "encoded" use style always defines a part with a
+        // type.
+        for each (var part:WSDLMessagePart in parts)
+        {
+            var encodedPartValues:XMLList;
+            var encodedPartValue:XML;
+            var decodedPart:*;
+            var partQName:QName;
+            var partType:QName;
+            var partDefinition:XML;
+
+            // If we have an element, use that to find the part
+            if (part.element != null)
+            {
+                if (outputMessageXML.hasComplexContent())
+                    encodedPartValues = outputMessageXML.elements(part.element);
+                else
+                    encodedPartValues = outputMessageXML.text();
+                partQName = part.element;
+                partType = null;
+            }
+            // Otherwise, find the part by name and decode using the 
+            // specified type definition
+            else
+            {
+                partType = part.type;
+                partDefinition = part.definition;
+
+                if (outputMessageXML.hasComplexContent())
+                {
+                    if (outputEncoding.useStyle == SOAPConstants.USE_ENCODED)
+                    {
+                        // First, look for the part with an unqualified name
+                        partQName = new QName("", part.name.localName);
+                        encodedPartValues = outputMessageXML.elements(partQName);
+
+                        if (encodedPartValues.length() == 0)
+                        {
+                            // HACK: Sometimes the soap:body namespace attribute
+                            // is used to qualify parts under the operation
+                            // wrapper, so we then look with this in mind...
+                            var encodedNamespace:String = outputEncoding.namespaceURI;
+                            partQName = new QName(encodedNamespace, part.name.localName);
+                            encodedPartValues = outputMessageXML.elements(partQName);
+
+                            // HACK: Sometimes the inputEncoding soap:body
+                            // namespace attribute is incorrectly used
+                            // for the output message parts too...
+                            if (encodedPartValues.length() == 0)
+                            {
+                                encodedNamespace = inputEncoding.namespaceURI;
+                                partQName = new QName(encodedNamespace, part.name.localName);
+                                encodedPartValues = outputMessageXML.elements(partQName);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        encodedPartValues = outputMessageXML.elements(part.name);
+                    }
+                }
+                else
+                {
+                    encodedPartValues = outputMessageXML.text();
+                }
+            }
+
+            for each (encodedPartValue in encodedPartValues)
+            {
+                decodedPart = decode(encodedPartValue, partQName, partType, partDefinition);
+
+                // Handle multiple output parts separately...
+                if (parts.length > 1)
+                {
+                    // Map multiple parts to named properties on the result object
+                    if (multiplePartsFormat == "object")
+                    {
+                        // Create the result object, if not created already
+                        // (this is the first part we have seen so far)
+                        if (result == null)
+                        {
+                            // The QName of the element that contains the part
+                            // values is used to look up a registered AS type
+                            // for the result object. For RPC operations the
+                            // QName will be the full operation name. For Doc/Lit
+                            // wrapped the QName will be the same as the
+                            // outputMessage.wrappedQName. For Doc/Lit bare
+                            // the QName will be soap:Body.
+                            result = createContent(outputMessageXML.name() as QName);
+                            result.isSimple = false;
+                        }
+                        
+                        if (result[part.name.localName] == null)
+                        {
+                            // We need to create an array for this part's values
+                            // if there are > 1 encodedPartValues, or we are
+                            // forcingPartArrays for parts defined with maxOccurs>1
+                            // regardless of number of values.
+                            var partMaxOccurs:uint = getMaxOccurs(partDefinition);
+                            if ((partMaxOccurs > 1 && forcePartArrays)
+                                    || encodedPartValues.length() > 1)
+                            {
+                                result[part.name.localName] = createIterableValue(part.type);
+                            }
+                        }
+
+                        // If we have created an iterable container, this part
+                        // value needs to be pushed on it
+                        if (TypeIterator.isIterable(result[part.name.localName]))
+                            TypeIterator.push(result[part.name.localName], decodedPart);
+                        // Otherwise just assign the single value to the named property.
+                        else
+                            result[part.name.localName] = decodedPart;
+                    }
+                    else if (multiplePartsFormat == "array")
+                    {
+                        // If multiplePartsFormat == "array", we return each part
+                        // as an element in an Array (or some registered collection)
+                        if (result == null)
+                        {
+                            // If this is the first part/value, we create the
+                            // array (or typed collection based on the container
+                            // element's QName)
+                            result = createIterableValue(outputMessageXML.name());
+                        }
+                        TypeIterator.push(result, decodedPart);
+                    }
+                }
+                else
+                {
+                    // Single output part. Create result object if not created.
+                    if (result == null)
+                    {
+                        // The result object with only one part becomes the part
+                        // itself. The type of the result object is the type of
+                        // the part (if the part specifies a type).
+                        var sinlgePartResultType:QName = partType;
+                        
+                        // If the part specifies an element, the type of the result
+                        // object is looked up based on the element QName.
+                        if (sinlgePartResultType == null)
+                            sinlgePartResultType = part.element;
+
+                        // If neither a type, nor element is specified (rare case
+                        // where part becomes anyType), the part.name is used to
+                        // look up a strong type for the result object.
+                        if (sinlgePartResultType == null)
+                            sinlgePartResultType = part.name;
+
+                        var singlePartMaxOccurs:uint = getMaxOccurs(partDefinition);
+                        if ((singlePartMaxOccurs > 1 && forcePartArrays)
+                                 || encodedPartValues.length() > 1)
+                        {
+                            // If more than one value was returned for a single
+                            // output part, or the part is defined with maxOccurs > 1,
+                            // we treat it as an array of values. The appropriate
+                            // IList class is created based on the singlePartResultType
+                            result = createIterableValue(sinlgePartResultType);
+                        }
+                        else
+                        {
+                            // decodedPart will already be an instance of the
+                            // required strong type (or ObjectProxy or Object).
+                            // If the single part has a single value, the result
+                            // object itself becomes that value, so we only need
+                            // a content proxy here.
+                            result = createContent();
+                        }
+                    }
+                    
+                    if (TypeIterator.isIterable(result))
+                    {
+                        // Push multiple values to the iterable result
+                        TypeIterator.push(result, decodedPart);
+                    }
+                    else
+                    {
+                        result = decodedPart;
+                    }
+                }
+            }
+        }
+
+        // If necessary, unwrap result from its proxy wrapper
+        if (result is ContentProxy)
+            result = ContentProxy(result).object_proxy::content;
+
+        soapResult.result = result;
+    }
+
+    /**
+     * Decodes a SOAP 1.1. Fault.
+     * 
+     * FIXME: We need to add SOAP 1.2 Fault support which is very different
+     * from SOAP 1.1.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function decodeFaults(faultsXMLList:XMLList):Array
+    {
+        log.debug("SOAP: Decoding SOAP response fault");
+        var faults:Array = [];
+
+        for each (var faultXML:XML in faultsXMLList)
+        {
+            var code:QName;
+            var string:String;
+            var detail:String;
+            var element:XML = faultXML;
+            var actor:String;
+
+            var faultProperties:XMLList = faultXML.children();
+            for each (var child:XML in faultProperties)
+            {
+                if (child.localName() == "faultcode")
+                {   
+                    code = schemaManager.getQNameForPrefixedName(child.toString(), child);
+                }
+                else if (child.localName() == "faultstring")
+                {
+                    string = child.toString();
+                }
+                else if (child.localName() == "faultactor")
+                {
+                    actor = child.toString();
+                }
+                else if (child.localName() == "detail")
+                {       
+                    if (child.hasComplexContent())
+                    {
+                        detail = child.children().toXMLString();    
+                    }
+                    else
+                    {
+                        detail = child.toString();
+                    }
+                }
+            }
+
+            var fault:SOAPFault = new SOAPFault(code, string, detail, element, actor);
+            faults.push(fault);
+        }
+        return faults;
+    }
+
+    protected function decodeHeaders(headerXML:XML):Array
+    {
+        log.debug("Decoding SOAP response headers");
+
+        var headers:Array = [];
+        var headerXMLList:XMLList = headerXML.elements();
+        for each (var headerChild:XML in headerXMLList)
+        {
+            if (headerFormat == "object")
+            {
+                var xsiType:QName = getXSIType(headerChild);
+                var definition:XML = null;
+                var headerContent:Object = null;
+
+                // Check for xsi:type on the header
+                if (xsiType != null)
+                    definition = schemaManager.getNamedDefinition(xsiType,
+                            constants.complexTypeQName, constants.simpleTypeQName);
+
+                // We found a definition for the type.
+                if (definition != null)
+                {
+                    // Release scope, since we were only checking if definition exists.
+                    schemaManager.releaseScope();
+                    headerContent = decode(headerChild, null, xsiType);
+                }
+                else
+                {
+                    // We don't have a type definition. Attempt to find an element
+                    // definition for the QName of the header. If there is none,
+                    // decode() will fall back to anyType.
+                    headerContent = decode(headerChild, headerChild.name() as QName);
+                }
+
+                // Create the SOAPHeader wrapper.
+                var headerObject:SOAPHeader = new SOAPHeader(headerChild.name() as QName, headerContent);
+
+                // decode mustUnderstand attribute
+                var muValue:String = XMLUtil.getAttributeByQName(headerChild,
+                            soapConstants.mustUnderstandQName).toString();
+                if (muValue == "1")
+                    headerObject.mustUnderstand = true;
+
+                // decode actor attribute
+                var actValue:String = XMLUtil.getAttributeByQName(headerChild,
+                            soapConstants.actorQName).toString();
+                if (actValue != "")
+                    headerObject.role = actValue;
+
+                headers.push(headerObject);
+            }
+            else if (headerFormat == "e4x")
+            {
+                headers.push(headerChild);
+            }
+            else if (headerFormat == "xml")
+            {
+                headers.push(new XMLDocument(headerChild.toString()));
+            }
+        }
+
+        return headers;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods - XML Decoding
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+    * @private
+    */
+    override public function decodeComplexType(definition:XML, parent:*, name:QName, value:*, restriction:XML=null, context:DecodingContext=null):void
+    {
+        if (value is XML)
+        {
+            var valXML:XML = value as XML;
+
+            if (valXML.elements(SOAPConstants.diffgramQName).length() > 0
+                && valXML.elements(schemaConstants.schemaQName).length() > 0)
+            {
+                // If we have XML with the elements of a .NET DataSet, we
+                // short-circuit to decodeType, which will call the special
+                // decode function for the DataSetType
+                decodeType(SOAPConstants.diffgramQName, parent, valXML.name() as QName, value);
+                return;
+            }
+        }
+
+        // If the value provided is not XML, or doesn't have the elements
+        // of a .NET DataSet, we just call super.
+        super.decodeComplexType(definition, parent, name, value, restriction, context);
+    }
+
+    /**
+     * @private
+     */
+    override public function decodeType(type:QName, parent:*, name:QName, value:*, restriction:XML = null):void
+    {
+        // SOAP encoding specifies a type directly on the value and we
+        // can usually use it unless it is a type that is not built-in
+        // nor has a schema type definition. The value's specific type is
+        // retained as originalType in case we need to fall back to using it.
+        var originalType:QName = type;
+        var xsiType:QName = getXSIType(value);
+        if (xsiType != null)
+            type = xsiType;
+
+        // HACK: If encoded, translate simple SOAP types to XSD types.
+        if (outputEncoding.useStyle == SOAPConstants.USE_ENCODED)
+        {
+            // FIXME: This should be managed by the schemaManager's unmarshaller
+            if (SOAPConstants.isSOAPEncodedType(type))
+            {
+                var datatypes:SchemaDatatypes = schemaManager.schemaDatatypes;
+                if (type == soapConstants.soapBase64QName)
+                {
+                    type = datatypes.base64BinaryQName;
+                }
+                else
+                {
+                    var localName:String = type.localName;
+                    if (localName != "Array" && localName != "arrayType")
+                    {
+                        type = schemaConstants.getQName(localName);
+                    }
+                }
+            }
+        }
+
+        // Look for a custom SOAP type to handle the decoding
+        var customType:ICustomSOAPType = SOAPConstants.getCustomSOAPType(type);
+        if (customType != null)
+        {
+            customType.decode(this, parent, name, value, restriction);
+            setXSIType(parent, type);
+        }
+        else
+        {
+            // We didn't do custom SOAP type decoding, so we need to delegate
+            // but we need to pass a valid type to the base processing routine.
+            var constants:SchemaConstants = schemaManager.schemaConstants;
+            if (isBuiltInType(type))
+            {
+                super.decodeType(type, parent, name, value, restriction);
+            }
+            else
+            {
+                var definition:XML = schemaManager.getNamedDefinition(type,
+                        constants.complexTypeQName,
+                        constants.simpleTypeQName,
+                        constants.elementTypeQName);
+
+                if (definition != null)
+                {
+                    // We're done with this definition; just needed to see if
+                    // we had it so we release the scope.
+                    schemaManager.releaseScope();
+                    super.decodeType(type, parent, name, value, restriction);
+                }
+                else
+                {
+                    // We don't have a type def for the value's specific
+                    // xsi type, so fall back to the default type passed in.
+                    super.decodeType(originalType, parent, name, value, restriction);
+                }
+            }
+        }
+    }
+
+    /**
+     * This override intercepts dencoding a complexType with complexContent based
+     * on a SOAP encoded Array. This awkward approach to Array type definitions
+     * was popular in WSDL 1.1 rpc-encoded operations and is a special case that
+     * needs to be handled, but note it violates the WS-I Basic Profile 1.0.
+     * 
+     * @private
+     */
+    override public function decodeComplexRestriction(restriction:XML, parent:*, name:QName, value:*):void
+    {
+        // Handle <restriction base="soap-enc:Array"> as a special case
+        var schemaConstants:SchemaConstants = schemaManager.schemaConstants;
+        var baseName:String = restriction.@base;
+        var baseQName:QName = schemaManager.getQNameForPrefixedName(baseName, restriction);
+        if (baseQName == soapConstants.soapencArrayQName)
+        {
+            var customType:ICustomSOAPType = SOAPConstants.getCustomSOAPType(baseQName);
+            if (customType != null)
+            {
+                customType.decode(this, parent, name, value, restriction);
+                return;
+            }
+        }
+
+        super.decodeComplexRestriction(restriction, parent, name, value);
+    }
+    
+    
+    override public function reset():void
+    {
+        super.reset();
+        _referencesResolved = false;
+        _elementsWithId = null;
+    }
+
+    /**
+     * Determines whether a name is in an internal (SOAP or XSD specific)
+     * namespace (as opposed to a user's namespace).
+     * @private 
+     */
+    override protected function isInternalNamespace(name:QName):Boolean
+    {
+        var uri:String = (name != null) ? name.uri : null;
+        if (uri)
+        {
+            if (URLUtil.urisEqual(uri, soapConstants.encodingURI) ||
+                URLUtil.urisEqual(uri, soapConstants.envelopeURI))
+            {
+                return true;
+            }
+        }
+
+        return super.isInternalNamespace(name);
+    }
+
+    /**
+     * Overrides XMLDecoder.parseValue to allow us to detect a legacy case
+     * of literal style encoding where by generically encoded compound types
+     * (such as arrays) had entries encoded with multiple child
+     * <code>item</code> elements (instead of matching the correct schema
+     * definition of just repeating the value node).
+     * 
+     * @private
+     */
+    override protected function parseValue(name:*, value:XMLList):*
+    {
+        if (supportGenericCompoundTypes 
+            && outputEncoding.useStyle == SOAPConstants.USE_LITERAL
+            && value.length() > 0)
+        {
+            // Look for child <item> elements as direct descendents of the value
+            var itemQName:QName = new QName(value[0].name().uri, "item");
+            var items:XMLList = value.elements(itemQName);
+            if (items.length() > 0)
+                value = items;
+        }
+
+        return super.parseValue(name, value);
+    }
+    
+    /**
+     * Overrides XMLDecoder.preProcessXML to allow us to handle multi-ref SOAP
+     * encoding.
+     * @private
+     */
+    override protected function preProcessXML(root:XML):void
+    {
+        // Only RPC/encoded uses multi-ref encoding.
+        if (outputEncoding.useStyle == SOAPConstants.USE_ENCODED)
+            resolveReferences(root);
+    }
+
+    /**
+     * Resolves multi-refs in rpc/encoded. Substitutes each reference by its
+     * referent node.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function resolveReferences(root:XML, cleanupElementsWithIdCache:Boolean=true):void
+    {
+        if (_referencesResolved)
+            return;
+
+        var index:uint = 0;
+        if (_elementsWithId == null)
+            _elementsWithId = document..*.(attribute("id").length() > 0);
+
+        // Note that we must consider all child nodes here, not just elements
+        // as we need the accurate index in terms of child XML nodes to replace
+        // a node with the referent.
+        for each (var child:XML in root.children())
+        {
+            if (child.nodeKind() == "element")
+            {
+                var href:String = getAttributeFromNode("href", child);
+                if (href != null)
+                {
+                    var hashPosition:int = href.indexOf("#");
+                    if (hashPosition >= 0)
+                        href = href.substring(hashPosition + 1);
+
+                    // Find the first element with a matching id attribute 
+                    var matches:XMLList = _elementsWithId.(@id == href);
+                    var referent:XML;
+
+                    if (matches.length() > 0)
+                        referent = matches[0];
+                    else
+                        throw new Error("The element referenced by id '" + href + "' was not found.");
+
+                    referent.setName(child.name());
+
+                    if (referent.hasComplexContent())
+                        resolveReferences(referent, false);
+
+                    // Replace the reference with the referent
+                    root.replace(index, referent);
+
+                    // Then remove the id attribute from replaced value
+                    referent = root.child(index)[0];
+                    delete referent.@id;
+                }
+                else if (child.hasComplexContent())
+                {
+                    resolveReferences(child, false);
+                }
+            }
+
+            index++;
+        }
+
+        if (cleanupElementsWithIdCache)
+        {
+            _elementsWithId = null;
+            // At this point all references have been resolved.
+            _referencesResolved = true;
+        }
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    
+    private var log:ILogger;
+    private var _elementsWithId:XMLList;
+    private var _forcePartArrays:Boolean;
+    private var _headerFormat:String;
+    private var _ignoreWhitespace:Boolean = true;
+    private var _multiplePartsFormat:String;
+    private var _referencesResolved:Boolean; // Used to prevent repeat resolution passes for a single document.
+    private var _resultFormat:String;
+    private var _wsdlOperation:mx.rpc.wsdl.WSDLOperation;
+
+
+    /**
+     * A RegEx pattern to help replace the whitespace between processing
+     * instructions and root tags.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static var PI_WHITESPACE_PATTERN:RegExp = new RegExp("[\\?][>]\\s*[<]", "g");
+}  
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPEncoder.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPEncoder.as
new file mode 100644
index 0000000..bc2880e
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPEncoder.as
@@ -0,0 +1,912 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+import flash.xml.XMLDocument;
+import flash.xml.XMLNode;
+
+import mx.core.mx_internal;
+import mx.logging.ILogger;
+import mx.logging.Log;
+import mx.resources.IResourceManager;
+import mx.resources.ResourceManager;
+import mx.rpc.soap.types.ICustomSOAPType;
+import mx.rpc.wsdl.WSDLConstants;
+import mx.rpc.wsdl.WSDLEncoding;
+import mx.rpc.wsdl.WSDLOperation;
+import mx.rpc.wsdl.WSDLMessage;
+import mx.rpc.wsdl.WSDLMessagePart;
+import mx.rpc.xml.Schema;
+import mx.rpc.xml.SchemaConstants;
+import mx.rpc.xml.SchemaDatatypes;
+import mx.rpc.xml.SchemaMarshaller;
+import mx.rpc.xml.XMLEncoder;
+
+[ResourceBundle("rpc")]
+
+[ExcludeClass]
+
+/**
+ * A SOAPEncoder is used to create SOAP 1.1 formatted requests for a web service
+ * operation. A WSDLOperation provides the definition of how SOAP request should
+ * be formatted and thus must be set before a call is made to encode().
+ * 
+ * TODO: Create a SOAP 1.2 specific subclass of this encoder.
+ * 
+ * @private
+ */
+public class SOAPEncoder extends XMLEncoder implements ISOAPEncoder
+{
+    //--------------------------------------------------------------------------
+    //
+    // Constructor
+    // 
+    //--------------------------------------------------------------------------
+
+    public function SOAPEncoder()
+    {
+        super();
+        log = Log.getLogger("mx.rpc.soap.SOAPEncoder");
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    private var resourceManager:IResourceManager =
+									ResourceManager.getInstance();
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Determines whether the encoder should ignore whitespace when
+     * constructing an XML representation of a SOAP request.
+     * The default is <code>true</code> and thus whitespace is not preserved.
+     * If an XML Schema type definition specifies a <code>whiteSpace</code>
+     * restriction set to <code>preserve</code> then ignoreWhitespace must
+     * first be set to false. Conversely, if a type <code>whiteSpace</code>
+     * restriction is set to <code>replace</code> or <code>collapse</code> then
+     * that setting will be honored even if ignoreWhitespace is set to false.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get ignoreWhitespace():Boolean
+    {
+        return _ignoreWhitespace;
+    }
+
+    public function set ignoreWhitespace(value:Boolean):void
+    {
+        _ignoreWhitespace = value;
+    }
+
+    /**
+     * @private
+     */
+    protected function get inputEncoding():WSDLEncoding
+    {
+        return _wsdlOperation.inputMessage.encoding;
+    }
+
+    public function get schemaConstants():SchemaConstants
+    {
+        return schemaManager.schemaConstants;
+    }
+
+    public function get soapConstants():SOAPConstants
+    {
+        return wsdlOperation.soapConstants;
+    }
+
+    public function get wsdlOperation():WSDLOperation
+    {
+        return _wsdlOperation;
+    }
+
+    public function set wsdlOperation(value:WSDLOperation):void
+    {
+        _wsdlOperation = value;
+        schemaManager = _wsdlOperation.schemaManager;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+    
+    /**
+	 *  @inheritDoc
+     */
+    public function encodeRequest(args:* = null, headers:Array = null):XML
+    {
+        // FIXME: Some level of validation should occur here
+        // to check we're ready to start encoding.
+
+        reset();
+
+        var envelopeXML:XML;
+
+        // Keep track of the previous ignoreWhitespace setting (as it is
+        // unfortunately a static API on the intrinsic XML type) so we
+        // can set it back to its original state once we're finished.
+        var oldIgnoreWhitespace:Boolean = XML.ignoreWhitespace;
+        var oldPrettyPrinting:Boolean = XML.prettyPrinting;
+        try
+        {
+            XML.ignoreWhitespace = ignoreWhitespace;
+            XML.prettyPrinting = false;
+            envelopeXML = encodeEnvelope(args, headers);
+        }
+        finally
+        {
+            XML.ignoreWhitespace = oldIgnoreWhitespace;
+            XML.prettyPrinting = oldPrettyPrinting;
+        }
+
+        return envelopeXML;
+    }
+
+    /**
+     * A SOAP Envelope element is the root element of a SOAP message. It
+     * must specify the SOAP namespace.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function encodeEnvelope(args:*, headers:Array):XML
+    {
+        log.debug("Encoding SOAP request envelope");
+
+        var envelopeXML:XML = <{soapConstants.envelopeQName.localName}/>;
+        envelopeXML.setNamespace(soapConstants.envelopeNamespace);
+        envelopeXML.addNamespace(schemaConstants.xsdNamespace);
+        envelopeXML.addNamespace(schemaConstants.xsiNamespace);
+        
+        // Make sure the envelope namespace is registered with the schemaManager
+        // so that its prefix can be looked up when encoding header attributes.
+        schemaManager.namespaces[soapConstants.envelopeNamespace.prefix] =
+                soapConstants.envelopeNamespace;
+        
+        encodeHeaders(headers, envelopeXML);
+        encodeBody(args, envelopeXML);
+        return envelopeXML;
+    }
+
+    /**
+     * Appends SOAP Header to the SOAP Envelope
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function encodeHeaders(headers:Array, envelopeXML:XML):void
+    {
+        if (headers != null)
+        {
+            var count:uint = headers.length;
+            if (count > 0)
+            {
+                var headersXML:XML = <{soapConstants.headerQName.localName}/> 
+                headersXML.setNamespace(soapConstants.envelopeNamespace);
+                envelopeXML.appendChild(headersXML);
+
+                for (var i:uint = 0; i < count; i++)
+                {
+                    encodeHeaderElement(headers[i], headersXML);
+                }
+            }
+        }
+    }
+
+    /**
+     * Appends a header element to top SOAP Header tag
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */ 
+    protected function encodeHeaderElement(header:Object, headersXML:XML):void
+    {
+        var preEncodedNode:* = preEncodedCheck(header);
+        if (preEncodedNode != null)
+        {
+            headersXML.appendChild(header);
+        }
+        else
+        {
+            var headerElement:XMLList = new XMLList();
+
+            // header value might contain a mapping 
+            if (header.content != null && header.content.hasOwnProperty(header.qname.localName))
+            {
+                header.content = header.content[header.qname.localName];
+            }
+
+            // check the content of the header for pre-encoded values
+            preEncodedNode = preEncodedCheck(header.content);
+            if (preEncodedNode != null)
+            {
+                // We can't set namespaces or attributes on XMLList, so we
+                // just append it and return...
+                if (preEncodedNode is XMLList)
+                {
+                    headerElement = preEncodedNode as XMLList;
+                }
+                else
+                {
+                    headerElement = new XMLList(preEncodedNode);
+                }
+            }
+            else
+            {
+                // If not pre-encoded, we encode the header value. If there is a
+                // definition in the schema for this header QName, we will use it,
+                // otherwise encode with anyType. This is handled by XMLEncoder.
+                headerElement = encode(header.content, header.qname);
+            }
+
+            
+            // Typically headerElement will be an XMLList of length 1, but we
+            // loop through it anyway, in case we were given a pre-encoded XMLList,
+            // or an array value for the header.content
+            for each (var headerElementNode:XML in headerElement)
+            {
+
+                // add namespace to the header, if not already set by encoding.
+                if (header.qname.uri != null && header.qname.uri.length > 0
+                    && headerElementNode.namespace().uri != header.qname.uri)
+                {
+                    var prefix:String = schemaManager.getOrCreatePrefix(header.qname.uri);
+                    var ns:Namespace = new Namespace(prefix, header.qname.uri);
+                    headerElementNode.setNamespace(ns);
+                }
+    
+                // add header attributes
+                var attrStr:String;
+                if (header.mustUnderstand)
+                {
+                    attrStr = schemaManager.getOrCreatePrefix(soapConstants.mustUnderstandQName.uri);
+                    headerElementNode.@[attrStr + ":" + soapConstants.mustUnderstandQName.localName] = "1"; // Use "1" form for WS-I compatibility
+                }
+    
+                if (header.role != null)
+                {
+                    attrStr = schemaManager.getOrCreatePrefix(soapConstants.actorQName.uri);
+                    headerElementNode.@[attrStr + ":" + soapConstants.actorQName.localName] = header.role;
+                }
+            }
+
+            // finally, add header list to SOAP Header node
+            headersXML.appendChild(headerElement);
+        }
+    }
+
+    /**
+     * Encodes the SOAP Body. Currently assumes only one operation sub-element.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function encodeBody(inputParams:*, envelopeXML:XML):void
+    {
+        log.debug("Encoding SOAP request body");
+
+        // Create SOAP Body element
+        var bodyXML:XML = <{soapConstants.bodyQName.localName}/>; 
+        bodyXML.setNamespace(soapConstants.envelopeNamespace);
+
+        // FIXME: Should we continue to support pre-encoded XML fragments here?
+        // How would we tell the difference between an XML type input and
+        // a pre-encoded message?
+
+        // Special case handling for input params that are pre-encoded SOAP
+        // body contents.
+        var preEncoded:Object = preEncodedCheck(inputParams);
+        if (preEncoded != null)
+        {
+            bodyXML.appendChild(preEncoded);
+        }
+        else
+        {
+            // Encode the operation and append it to the body.
+            if (wsdlOperation.style == SOAPConstants.DOC_STYLE)
+            {
+                if (inputEncoding.useStyle == SOAPConstants.USE_LITERAL)
+                {
+                    encodeOperationAsDocumentLiteral(inputParams, bodyXML);
+                }
+                else
+                {
+                    //Note: document-encoded not support by WSDL 1.1
+                    throw new Error("WSDL 1.1 supports operations with binding style 'document' only if use style is 'literal'.");
+                }
+            }
+            else if (wsdlOperation.style == SOAPConstants.RPC_STYLE)
+            {
+               if (inputEncoding.useStyle == SOAPConstants.USE_LITERAL)
+               {    
+                    encodeOperationAsRPCLiteral(inputParams, bodyXML);
+               }
+               else if (inputEncoding.useStyle == SOAPConstants.USE_ENCODED)
+               {
+                   encodeOperationAsRPCEncoded(inputParams, bodyXML);
+               }
+               else
+               {
+                   throw new Error("WSDL 1.1 does not support operations with binding style 'rpc' and use style " + inputEncoding.useStyle + ".");
+               }
+            }
+            else
+            {
+                throw new Error("Unrecognized binding style '" + wsdlOperation.style + "'. Only 'document' and 'rpc' styles are supported.");
+            }
+        }
+
+        // Add the fully encoded body to the envelope.
+        envelopeXML.appendChild(bodyXML);
+    }
+    
+    /**
+     * Encodes a WSDL operation using document literal format.
+     * There's no need to generate an operation element so advance directly
+     * to encoding the message.
+     * <p>
+     * From the WSDL 1.1 specification:
+     * </p>
+     * <p>
+     * &quot;If <code>use</code> is <b>literal</b>, then each part references
+     * a concrete schema definition using either the <code>element</code> or
+     * <code>type</code> attribute. In the first case, the element referenced
+     * by the part will appear directly under the Body element (for document
+     * style bindings)... In the second, the type referenced by the part
+     * becomes the schema type of the enclosing element (Body for document
+     * style...).&quot;
+     * </p>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function encodeOperationAsDocumentLiteral(inputParams:Object, bodyXML:XML):void
+    {
+        var parts:Array = wsdlOperation.inputMessage.parts;
+        if (wsdlOperation.inputMessage.isWrapped)
+        {
+            // Wrapped-style uses a single part element as the outer wrapper.
+            var wrappedQName:QName = wsdlOperation.inputMessage.wrappedQName;
+            var operationXML:XML = <{wrappedQName.localName}/>;
+            if (wrappedQName.uri != null && wrappedQName.uri != "")
+            {
+                var prefix:String = schemaManager.getOrCreatePrefix(wrappedQName.uri);
+                var inputNamespace:Namespace = new Namespace(prefix, wrappedQName.uri);
+                operationXML.setNamespace(inputNamespace);
+            }
+
+            encodeMessage(inputParams, operationXML);
+            bodyXML.appendChild(operationXML);
+        }
+        else
+        {
+            // Non-wrapped document-literal style directly encodes the parts
+            // as children of the SOAP Body.
+            encodeMessage(inputParams, bodyXML);
+        }
+    }
+    
+    /**
+     * Encodes a WSDL operation using RPC literal format.
+     * <p>
+     * From the WSDL 1.1 specification:
+     * </p>
+     * <p>
+     * &quot;If the operation style is <code>rpc</code> each part is a parameter
+     * or a return value and appears inside a wrapper element within the body
+     * (following Section 7.1 of the SOAP specification). The wrapper element
+     * is named identically to the operation name and its namespace is the
+     * value of the namespace attribute. Each message part (parameter) appears
+     * under the wrapper, represented by an accessor named identically to the
+     * corresponding parameter of the call. Parts are arranged in the same
+     * order as the parameters of the call.&quot;
+     * </p>
+     * <p>
+     * &quot;If <code>use</code> is <b>literal</b>, then each part references
+     * a concrete schema definition using either the <code>element</code> or
+     * <code>type</code> attribute. In the first case, the element referenced
+     * by the part will appear ... under an accessor element named after the
+     * message part (in rpc style). In the second, the type referenced by the
+     * part becomes the schema type of the enclosing element ( ... part accessor
+     * element for rpc style).&quot;
+     * </p>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function encodeOperationAsRPCLiteral(inputParams:Object, bodyXML:XML):void
+    {
+        var operationXML:XML = <{wsdlOperation.name}/>;
+        var prefix:String = schemaManager.getOrCreatePrefix(inputEncoding.namespaceURI);
+        var ns:Namespace = new Namespace(prefix, inputEncoding.namespaceURI);
+        operationXML.setNamespace(ns);
+
+        encodeMessage(inputParams, operationXML);
+        
+        bodyXML.appendChild(operationXML);
+    }
+    
+    /**
+     * Encodes a WSDL message part using RPC encoded format.
+     * <p>
+     * From the WSDL 1.1 specification:
+     * </p>
+     * <p>
+     * &quot;If the operation style is <code>rpc</code> each part is a parameter
+     * or a return value and appears inside a wrapper element within the body
+     * (following Section 7.1 of the SOAP specification). The wrapper element
+     * is named identically to the operation name and its namespace is the
+     * value of the namespace attribute. Each message part (parameter) appears
+     * under the wrapper, represented by an accessor named identically to the
+     * corresponding parameter of the call. Parts are arranged in the same
+     * order as the parameters of the call.&quot;
+     * </p>
+     * <p>
+     * &quot;If <code>use</code> is <b>encoded</b>, then each message part
+     * references an abstract type using the <code>type</code> attribute. These
+     * abstract types are used to produce a concrete message by applying an
+     * encoding specified by the <code>encodingStyle</code> attribute. The part
+     * names, types and value of the namespace attribute are all inputs to the
+     * encoding, although the namespace attribute only applies to content not
+     * explicitly defined by the abstract types. If the referenced encoding
+     * style allows variations in it's format (such as the SOAP encoding does),
+     * then all variations MUST be supported ("reader makes right").&quot;
+     * </p>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function encodeOperationAsRPCEncoded(inputParams:*, bodyXML:XML):void
+    {
+        isSOAPEncoding = true;        
+        var operationXML:XML = <{wsdlOperation.name}/>;
+        var inputNamespaceURI:String = inputEncoding.namespaceURI;
+        var inputPrefix:String = schemaManager.getOrCreatePrefix(inputNamespaceURI);
+        var inputNamespace:Namespace = new Namespace(inputPrefix, inputNamespaceURI);
+        operationXML.setNamespace(inputNamespace);
+
+        encodeMessage(inputParams, operationXML); 
+
+        bodyXML.appendChild(operationXML);
+        bodyXML.@[SOAPConstants.SOAP_ENV_PREFIX + ":encodingStyle"] = soapConstants.encodingURI;        
+    }    
+
+    /**
+     * Encodes an input message for a WSDL operation. The provided input
+     * parameters are validated against the required message parts.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function encodeMessage(inputParams:*, operationXML:XML):void
+    {
+        var parts:Array;
+        if (wsdlOperation.inputMessage != null)
+            parts = wsdlOperation.inputMessage.parts;
+
+        if (parts == null)
+            return;
+
+        // Keep track of part names for validation
+        var partNames:Object = {};
+
+        // Keep track of any optional parts that were not provided
+        var optionalOmitted:int = 0;
+
+		var message:String;
+
+        // Match the input parameters to WSDL message parts
+        for (var i:uint = 0; i < parts.length; i++)
+        {
+            var part:WSDLMessagePart = parts[i];
+            var value:* = undefined;
+
+            // Ordered Parameters
+            if (inputParams is Array)
+            {
+                value = inputParams[i];
+                if (value === undefined)
+                {
+                    if (part.optional)
+					{
+                        optionalOmitted++;
+					}
+                    else
+					{
+						message = resourceManager.getString(
+							"rpc", "missingInputParameter", [ i ]);
+                        throw new Error(message);
+					}
+                }
+            }
+            // Named Parameters
+            else
+            {
+                var name:String = part.name.localName;
+                if (inputParams != null)
+                    value = inputParams[name];
+                partNames[name] = value;
+
+                if (value === undefined || (inputParams != null && !inputParams.hasOwnProperty(name)))
+                {
+                    if (part.optional)
+					{
+                        optionalOmitted++;
+					}
+                    else
+					{
+						message = resourceManager.getString(
+							"rpc", "missingInputParameterWithName", [ name ])
+                        throw new Error(message);
+					}
+                }
+            }
+
+            if (value !== undefined)
+            {
+                // Finally, encode the value for the WSDL message part
+                var partXMLList:XMLList = encodePartValue(part, value);
+                operationXML.appendChild(partXMLList);
+            }
+        }
+
+        // Check for any unexpected parameters
+        if (inputParams != null)
+        {
+            if (inputParams is Array)
+            {
+                if (inputParams.length < (parts.length - optionalOmitted))
+                {
+					message = resourceManager.getString(
+						"rpc", "tooFewInputParameters",
+						[ parts.length, inputParams.length ]);
+                    throw new Error(message);
+                }
+            }
+            else
+            {
+                for (var inName:String in inputParams)
+                {
+                    if (!partNames.hasOwnProperty(inName))
+                    {
+						message = resourceManager.getString(
+							"rpc", "unexpectedInputParameter", [ inName ]);
+                        throw new Error(message);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * A WSDL message part may either refer to an XML Schema type (that is, a
+     * &lt;complexType&gt; or &lt;simpleType&gt;) directly by QName or to an element
+     * definition by QName depending on the SOAP use and encodingStyle
+     * attributes.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function encodePartValue(part:WSDLMessagePart, value:*):XMLList
+    {
+        var partXMLList:XMLList;
+
+        if (part.element != null)
+        {
+            partXMLList = encode(value, part.element);
+        }
+        else
+        {
+            partXMLList = encode(value, part.name, part.type, part.definition);
+        }
+
+        return partXMLList;
+    }
+
+    /**
+     * Looks to see whether a pre-encoded SOAP request has been passed to the
+     * encoder.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function preEncodedCheck(value:*):Object
+    {
+        var preEncodedNode:Object = null;
+        if (value != null)
+        {
+            if (value is XMLList)
+            {
+                preEncodedNode = value as XMLList;
+            }
+            else if (value is XML)
+            {
+                preEncodedNode = value as XML;
+            }
+            else if (value is XMLDocument)
+            {
+                var xmlDocument:XMLDocument = value as XMLDocument;
+                preEncodedNode = new XML(xmlDocument.firstChild.toString());
+            }
+            else if (value is XMLNode)
+            {
+                var xmlNode:XMLNode = value as XMLNode;
+                preEncodedNode = new XML(xmlNode.toString());
+            }
+        }
+        return preEncodedNode;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Custom XML Encoding Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * SOAP specific override to handle special wrapped-style document-literal 
+     * parameters which can specify minOccurs and maxOccurs attributes on
+     * local element definitions that are, for all intents and purposes,
+     * really top-level element definitions representing operation parts.
+     * XML Schema does not normally allow minOccurs or maxOccurs on top-level
+     * element definitions and the SchemaProcessor is not looking out for them
+     * so we have to special case this situation here.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function encode(value:*, name:QName = null, type:QName = null, definition:XML = null):XMLList
+    {
+        if (definition != null)
+        {
+            var result:XMLList = new XMLList();
+
+            // <element minOccurs="..." maxOccurs="..."> occur on a local element
+            // that may act like a top-level element for wrapped-style document
+            // literal.
+            var maxOccurs:uint = getMaxOccurs(definition);
+            var minOccurs:uint = getMinOccurs(definition);
+
+            // If the maximum occurence should 0 this element must not be present.
+            if (maxOccurs == 0)
+                return result;
+
+            // If minOccurs == 0 the element is optional so we can omit it if
+            // a value was not provided.
+            if (value == null && minOccurs == 0)
+                return result;
+
+            if (maxOccurs > 1)
+            {
+                // Create a temporary XML parent to hold the XMLList of values
+                // during encoding ...
+                var content:XMLList = new XMLList();
+                // To make sure we will use the correct namespace if there are more
+                // than one top level schemas, we push the relevant schema as a new scope.
+                var foundScope:Boolean = schemaManager.pushNamespaceInScope(name.uri);
+                
+                encodeGroupElement(definition, content, name, value);
+                
+                if (foundScope)
+                    schemaManager.releaseScope();
+
+                result += content;
+                return result;
+            }
+        }
+
+        return super.encode(value, name, type, definition);
+    }
+
+    /**
+     * SOAP specific override to intercept SOAP encoded types such as base64.
+     * Also, SOAP encoding requires an XSI type attribute to be specified on
+     * encoded types.
+     * 
+     * @private
+     */
+    override public function encodeType(type:QName, parent:XML, name:QName, value:*, restriction:XML = null):void
+    {
+        var datatypes:SchemaDatatypes = schemaManager.schemaDatatypes;
+
+        // Allow instance level overrides for the type (which can also be used
+        // to specify the XSI type too).
+        var xsiType:QName = getXSIType(value);
+        if (xsiType != null)
+            type = xsiType;
+
+        // We can encode many SOAP types as their XML Schema equivalents so
+        // long as we set the XSI type correctly for SOAP encoded operations
+        if (isSOAPEncoding)
+        {
+            // Keep track of the real type for setting the SOAP encoding
+            // xsi:type as we may need to use a different type internally for
+            // XML Schema encoding...
+            xsiType = type;
+
+            if (SOAPConstants.isSOAPEncodedType(type))
+            {
+                // We treat SOAP encoded base64 as the XML Schema base64Binary
+                if (type == soapConstants.soapBase64QName)
+                {
+                    type = datatypes.base64BinaryQName;
+                }
+                else
+                {
+                    // HACK: Translate simple SOAP encoded types to XSD types
+                    // for the purposes of schema type marshalling
+                    var localName:String = type.localName;
+                    if (localName != "Array" && localName != "arrayType")
+                    {
+                        type = schemaConstants.getQName(localName);
+                    }
+                }
+            }
+        }
+
+        // Look for custom handlers to override processing of SOAP types.
+        var customType:ICustomSOAPType = SOAPConstants.getCustomSOAPType(type);
+        if (customType != null)
+        {
+            customType.encode(this, parent, name, value, restriction);
+        }
+        else
+        {
+            super.encodeType(type, parent, name, value, restriction);
+        }
+
+        // Finally, we may need to set an xsi:type attribute on the parent...
+        if (xsiType != null)
+        {
+//            var parentNode:XML = parent as XML;
+
+            // ... but we don't override if an existing xsi:type was determined
+            // up stream (ie.. for anyType and anySimpleType).
+            var xsiTypeAttr:String = parent.@[schemaConstants.getXSIToken(schemaConstants.typeAttrQName)]
+            if (xsiTypeAttr == null || xsiTypeAttr == "")
+            {
+                // FIXME: we shouldn't need super anymore since deriveXSIType is separate
+                super.setXSIType(parent, xsiType);
+            }
+        }
+    }
+
+    /**
+     * This override intercepts encoding a complexType with complexContent based
+     * on a SOAP encoded Array. This awkward approach to Array type definitions
+     * was popular in WSDL 1.1 rpc-encoded operations and is a special case that
+     * needs to be handled, but note it violates the WS-I Basic Profile 1.0.
+     * 
+     * @private
+     */
+    override public function encodeComplexRestriction(restriction:XML, parent:XML, name:QName, value:*):void
+    {
+        // Handle for <restriction base="soap-enc:Array"> as a special case
+        var schemaConstants:SchemaConstants = schemaManager.schemaConstants;
+        var baseName:String = restriction.@base;
+        var baseQName:QName = schemaManager.getQNameForPrefixedName(baseName, restriction);
+        if (baseQName == soapConstants.soapencArrayQName)
+        {
+            var customType:ICustomSOAPType = SOAPConstants.getCustomSOAPType(baseQName);
+            if (customType != null)
+            {
+                customType.encode(this, parent, name, value, restriction);
+                return;
+            }
+        }
+
+        super.encodeComplexRestriction(restriction, parent, name, value);
+    }
+
+    /**
+     * This override tries to determine the XSI type for the encoded value if
+     * SOAP use style is set to <code>encoded</code>.
+     * 
+     * @private
+     */
+    protected override function deriveXSIType(parent:XML, type:QName, value:*):void
+    {
+
+        // Add XSI type if the SOAP message has use style as "encoded"
+        if (isSOAPEncoding)
+        {
+            var datatypes:SchemaDatatypes = schemaManager.schemaDatatypes;
+            var soapType:QName;
+
+            // HACK: For anyType and anySimpleType, try to guess the schema
+            // type for simple values (note we can't guess for complex values).
+            if (type == datatypes.anyTypeQName || type == datatypes.anySimpleTypeQName)
+            {
+                if (isSimpleValue(value) || type == datatypes.anySimpleTypeQName)
+                {
+                    var localName:String = SchemaMarshaller.guessSimpleType(value);
+                    soapType = new QName(schemaConstants.xsdURI, localName);
+                }
+            }
+            else
+            {
+                soapType = type;
+            }
+            
+            if (soapType != null)
+            {
+                // FIXME: should be OK to use setXSIType
+//                setXSIType(parent, soapType);
+                parent.@[schemaConstants.getXSIToken(schemaConstants.typeAttrQName)] = schemaConstants.getXSDToken(soapType);
+            }
+        }
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    private var _ignoreWhitespace:Boolean = true;
+    private var isSOAPEncoding:Boolean = false;
+    private var log:ILogger;
+    private var _wsdlOperation:WSDLOperation;
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPFault.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPFault.as
new file mode 100644
index 0000000..900abf3
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPFault.as
@@ -0,0 +1,183 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+import flash.xml.XMLNode;
+import mx.rpc.Fault;
+
+/**
+ * A subclass of mx.rpc.Fault that provides SOAP specific information from
+ * a SOAP envelope Fault element.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class SOAPFault extends Fault
+{
+    /**
+     * Constructs a new SOAPFault.
+     *
+     * @param faultCode The fully qualified name of the fault code.
+     * 
+     * @param faultString The description of the fault.
+     *
+     * @param detail Any extra details of the fault.
+     *
+     * @param element The raw XML of the SOAP fault.
+     *
+     * @param faultactor Information about who caused the SOAP fault.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function SOAPFault(faultCode:QName,
+                       faultString:String,
+                       detail:String = null,
+                       element:XML = null,
+                       faultactor:String = null)
+    {
+        super(faultCode.localName, faultString, detail);
+
+        this.element = element;
+        this.faultactor = faultactor;
+        this.faultcode = faultCode;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * The raw XML of this SOAP Fault.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var element:XML;
+
+    /**
+     * A SOAP Fault may provide information about who caused the fault through
+     * a faultactor property.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var faultactor:String;
+
+    /**
+     * The faultcode property is similar to faultCode but exists to both
+     * match the case of the faultcode element in a SOAP Fault and to provide
+     * the fully qualified name of the code.
+     * 
+     * @see mx.rpc.Fault#faultDetail
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var faultcode:QName;
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * The detail property is the same as faultDetail but exists
+     * to match the case of the detail element in a SOAP Fault.
+     * 
+     * @see mx.rpc.Fault#faultDetail
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get detail():String
+    {
+        return _faultDetail;
+    }
+
+    public function set detail(value:String):void
+    {
+        _faultDetail = value;
+    }
+
+    /**
+     * The faultstring property is the same as faultString but exists
+     * to match the case of the faultstring element in a SOAP envelope Fault.
+     * 
+     * @see mx.rpc.Fault#faultString
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get faultstring():String
+    {
+        return _faultString;
+    }
+
+    public function set faultstring(value:String):void
+    {
+        _faultString = value;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Returns the String "SOAPFault" plus the faultCode, faultString, and
+     * faultDetail.
+     *
+     * @return Returns the String "SOAPFault" plus the faultCode, faultString, and
+     * faultDetail.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function toString():String
+    {
+        return "SOAPFault (" + faultCode + "): " + faultString + " " + faultDetail;
+    }
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPHeader.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPHeader.as
new file mode 100644
index 0000000..68db529
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPHeader.as
@@ -0,0 +1,120 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+/**
+ * You use a SOAPHeader to specify the headers that need 
+ * to be added to a SOAP envelope of a WebService Operation request.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class SOAPHeader
+{
+    /**
+     * Constructs a new SOAPHeader. The qualified name and content for the
+     * SOAP header are required.
+     *
+     * @param qname The qualified name of the SOAP header.
+     *
+     * @param content The content to send for the header value.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function SOAPHeader(qname:QName, content:Object)
+    {
+        super();
+        this.qname = qname;
+        this.content = content;
+    }
+
+    /**
+     * The content to send for the header value. 
+     * If you provide an XML or flash.xml.XMLNode instance for the header, it is
+     * used directly as pre-encoded content and appended as a child to the soap:header element.
+     * Otherwise, you can provide the value as a String or Number, etc. and the underlying SOAP encoder
+     * attempts to encode the value correctly based on the QName provided in the SOAPHeader
+     * (with the last resort being xsd:anyType if a type definition is not present).     
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var content:Object;
+
+    /**
+     * The qualified name of the SOAP header.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var qname:QName;
+
+    /**
+     * Internal use only. The internal datatype as determined from
+     * the WSDL schema that should be used to encode the content.
+     * @private
+     */
+    public var xmlType:QName;
+
+    /**
+     * Specifies whether the header must be understood by the endpoint. If
+     * the header is handled but must be understood the endpoint should
+     * return a SOAP fault.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var mustUnderstand:Boolean;
+    
+    /**
+     * Specifies the URI for the role that this header is intended in a 
+     * potential chain of endpoints processing a SOAP request. If defined, 
+     * this value is used to specify the <code>actor</code> for the SOAP 
+     * header.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var role:String;
+
+    /**
+     * @private
+     */
+    public function toString():String
+    {
+        return qname + ", " + content + ", " + role; 
+    }
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPResult.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPResult.as
new file mode 100644
index 0000000..b3f2207
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/SOAPResult.as
@@ -0,0 +1,81 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap
+{
+
+
+/**
+ * A context for the result of a SOAP based Remote Procedure Call.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class SOAPResult
+{
+    /**
+     * A collection of header objects. A SOAPDecoder can populate this array with
+     * elements of type SOAPHeader, XML, or XMLDocument, based on the headerFormat
+     * setting on the decoder.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var headers:Array;
+    
+    /**
+     * Flag indicating if this result object represents a SOAP Fault message.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var isFault:Boolean;
+    
+    /**
+     * Body of the SOAP result. A SOAPDecoder can populate this value based on the
+     * resultFormat setting on the decoder.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var result:*;
+
+    /**
+     * Creates a new SOAPResult.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function SOAPResult()
+    {
+        super();
+    }
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/WebService.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/WebService.as
index d35fce4..e506674 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/WebService.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/WebService.as
@@ -25,7 +25,7 @@ package mx.rpc.soap
  import org.apache.royale.events.Event;
  
 import mx.core.mx_internal;
-/* import mx.logging.ILogger;
+import mx.logging.ILogger;
 import mx.logging.Log;
 import mx.messaging.ChannelSet;
 import mx.messaging.channels.DirectHTTPChannel;
@@ -44,8 +44,7 @@ import mx.rpc.wsdl.WSDLLoader;
 import mx.rpc.wsdl.WSDLOperation;
 import mx.rpc.wsdl.WSDLPort;
 import mx.utils.URLUtil;
-import mx.utils.XMLUtil;
- */
+
 use namespace mx_internal;
 
 /**
@@ -59,9 +58,9 @@ use namespace mx_internal;
  *  @playerversion AIR 1.1
  *  @productversion Royale 0.9.4
  */
-/* [Event(name="load", type="mx.rpc.soap.LoadEvent")]
+[Event(name="load", type="mx.rpc.soap.LoadEvent")]
 
-[ResourceBundle("rpc")] */
+//[ResourceBundle("rpc")]
 
 /**
  * The WebService class provides access to SOAP-based web services on remote
@@ -72,8 +71,8 @@ use namespace mx_internal;
  *  @playerversion AIR 1.1
  *  @productversion Royale 0.9.4
  */
-public dynamic class WebService
-{ // extends AbstractWebService
+public dynamic class WebService extends AbstractWebService
+{ 
     //--------------------------------------------------------------------------
     //
     // Constructor
@@ -98,10 +97,10 @@ public dynamic class WebService
      */
     public function WebService(destination:String = null, rootURL:String = null)
     {
-      /*   super(destination, rootURL);
+        super(destination, rootURL);
 
         _ready = false;
-        _log = Log.getLogger("mx.rpc.soap.WebService"); */
+        _log = Log.getLogger("mx.rpc.soap.WebService");
     }
 
     //-------------------------------------------------------------------------
@@ -121,12 +120,12 @@ public dynamic class WebService
     //
     //-------------------------------------------------------------------------
 
-    /* mx_internal function get wsdlFault():Boolean
+    mx_internal function get wsdlFault():Boolean
     {
         return _wsdlFault;
     }
 
-    [Inspectable(defaultValue="true", category="General")] */
+    [Inspectable(defaultValue="true", category="General")]
 
     /**
      * The location of the WSDL document for this WebService. If you use a
@@ -138,7 +137,7 @@ public dynamic class WebService
      *  @playerversion AIR 1.1
      *  @productversion Royale 0.9.4
      */
-   /*  public function get wsdl():String
+    public function get wsdl():String
     {
         return _wsdlURL;
     }
@@ -146,7 +145,7 @@ public dynamic class WebService
     public function set wsdl(w:String):void
     {
         _wsdlURL = w;
-    } */
+    }
 
     //-------------------------------------------------------------------------
     //
@@ -166,7 +165,7 @@ public dynamic class WebService
      *  @playerversion AIR 1.1
      *  @productversion Royale 0.9.4
      */
-   /*  public function canLoadWSDL():Boolean
+    public function canLoadWSDL():Boolean
     {
         if (wsdl)
             return true;
@@ -174,7 +173,7 @@ public dynamic class WebService
             && destination != DEFAULT_DESTINATION_HTTPS)
             return true;
         return false;
-    } */
+    }
 
     /**
      * Returns an Operation of the given name. If the Operation wasn't
@@ -192,7 +191,7 @@ public dynamic class WebService
      *  @playerversion AIR 1.1
      *  @productversion Royale 0.9.4
      */
-    /* override public function getOperation(name:String):mx.rpc.AbstractOperation
+    override public function getOperation(name:String):mx.rpc.AbstractOperation
     {
         var op:mx.rpc.AbstractOperation = super.getOperation(name);
         if (op == null)
@@ -204,7 +203,7 @@ public dynamic class WebService
             initializeOperation(op as Operation);
         }
         return op;
-    } */
+    }
 
     /**
      * Instructs the WebService to download the WSDL document.  The WebService
@@ -223,7 +222,7 @@ public dynamic class WebService
      */
     public function loadWSDL(uri:String = null):void
     {
-       /*  if (uri != null)
+        if (uri != null)
         {
             wsdl = uri;
         }
@@ -235,8 +234,8 @@ public dynamic class WebService
 			var message:String;
             if (!useProxy)
             {
-				message = resourceManager.getString(
-					"rpc", "mustSpecifyWSDLLocation");
+				message = /*resourceManager.getString(
+					"rpc", */"mustSpecifyWSDLLocation"/*)*/;
                 var fault:Fault = new Fault("Client.WSDL", message);
                 dispatchEvent(FaultEvent.createEvent(fault));
                 return;
@@ -245,8 +244,8 @@ public dynamic class WebService
                 || (destination == DEFAULT_DESTINATION_HTTP) 
                 || (destination == DEFAULT_DESTINATION_HTTPS))
             {
-				message = resourceManager.getString(
-					"rpc", "destinationOrWSDLNotSpecified");
+				message = /*resourceManager.getString(
+					"rpc", */"destinationOrWSDLNotSpecified"/*)*/;
                 var fault1:Fault = new Fault("Client.WSDL", message);
                 dispatchEvent(FaultEvent.createEvent(fault1));
                 return;
@@ -269,7 +268,7 @@ public dynamic class WebService
 
         // Get the WSDL
         _wsdlFault = false;
-        _wsdlLoader.load(wsdl); */
+        _wsdlLoader.load(wsdl);
     }
 
     /**
@@ -284,7 +283,8 @@ public dynamic class WebService
      *  @playerversion AIR 1.1
      *  @productversion Royale 0.9.4
      */
-   /*  public function toString():String
+    COMPILE::JS { override }
+    public function toString():String
     {
         var s:String = "[WebService ";
         s += " destination=\"" + destination + "\"";
@@ -292,13 +292,13 @@ public dynamic class WebService
             s += " wsdl=\"" + wsdl + "\"";
         s += " channelSet=\"" + channelSet + "\"]";
         return s;
-    } */
+    }
 
     //---------------------------------
     // Helper methods
     //---------------------------------
 
-    /* mx_internal function wsdlFaultHandler(event:FaultEvent):void
+    mx_internal function wsdlFaultHandler(event:FaultEvent):void
     {
         // remember that the wsdl failed
         _wsdlFault = true;
@@ -308,9 +308,9 @@ public dynamic class WebService
 
         // also inform enqueued operations of the wsdl failure
         unEnqueueCalls(event.fault);
-    } */
+    }
 
-    /* mx_internal function wsdlHandler(event:WSDLLoadEvent):void
+    mx_internal function wsdlHandler(event:WSDLLoadEvent):void
     {
         _log.debug("WSDL loaded");
         _wsdl = event.wsdl;
@@ -355,8 +355,8 @@ public dynamic class WebService
         catch(error:Error)
         {
             var errorMessage:String = error.message ? error.message : ""; 
-			var message:String =  resourceManager.getString(
-				"rpc", "unexpectedException", [ errorMessage ])          
+			var message:String =  /*resourceManager.getString(
+				"rpc",*/ "unexpectedException" /*, [ errorMessage ])*/;          
             var fault:Fault = new Fault("WSDLError", message);
             fault.rootCause = error;
             var faultEvent2:FaultEvent = FaultEvent.createEvent(fault);
@@ -364,12 +364,12 @@ public dynamic class WebService
             super.unEnqueueCalls(fault); // Jump straight to fault handling; ops cannot be initialized.
             return;
         }
-    } */
+    }
 
     /**
      * @private
      */
-    /* mx_internal function deriveHTTPService():HTTPService
+    mx_internal function deriveHTTPService():HTTPService
     {
         var httpService:HTTPService = new HTTPService();
         httpService.asyncRequest = asyncRequest;
@@ -381,7 +381,7 @@ public dynamic class WebService
         httpService.rootURL = rootURL;
         httpService.headers = httpHeaders;
         return httpService;
-    } */
+    }
 
    /**
     * Initializes a new Operation.
@@ -393,7 +393,7 @@ public dynamic class WebService
     *  @playerversion AIR 1.1
     *  @productversion Royale 0.9.4
     */
-    /* protected function initializeOperation(operation:Operation):void
+    protected function initializeOperation(operation:Operation):void
     {
         if (_wsdl != null)
         {
@@ -402,32 +402,32 @@ public dynamic class WebService
                 operation.endpointURI = endpointURI;
             operation.wsdlOperation = wsdlOp;
         }
-    } */
+    }
 
-    /* private function dispatchFault(faultCode:String, faultString:String, faultDetail:String = null):void
+    private function dispatchFault(faultCode:String, faultString:String, faultDetail:String = null):void
     {
         var fault:Fault = new Fault(faultCode, faultString, faultDetail);
         var event:FaultEvent = FaultEvent.createEvent(fault);
         dispatchEvent(event);
-    } */
+    }
 
     //--------------------------------------------
     // Backing variables for public getter/setters
     //--------------------------------------------
     
-	//private var _wsdlURL:String;
+	private var _wsdlURL:String;
 
     //---------------------------------
     // Internal properties
     //---------------------------------
     
-	/* private var _log:ILogger;
+	private var _log:ILogger;
     
 	private var _wsdlFault:Boolean;
     
 	private var _wsdl:mx.rpc.wsdl.WSDL;
     
-	private var _wsdlLoader:WSDLLoader; */
+	private var _wsdlLoader:WSDLLoader;
 
     //--------------------------------------------------------------------------
     //
@@ -435,9 +435,9 @@ public dynamic class WebService
     // 
     //--------------------------------------------------------------------------
 
-    /* public static const DEFAULT_DESTINATION_HTTP:String = "DefaultHTTP";
+    public static const DEFAULT_DESTINATION_HTTP:String = "DefaultHTTP";
     
-	public static const DEFAULT_DESTINATION_HTTPS:String = "DefaultHTTPS"; */
+	public static const DEFAULT_DESTINATION_HTTPS:String = "DefaultHTTPS";
 }
 
 }
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/mxml/Operation.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/mxml/Operation.as
new file mode 100644
index 0000000..4f44b48
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/mxml/Operation.as
@@ -0,0 +1,272 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap.mxml
+{
+
+import mx.core.mx_internal;
+import mx.managers.CursorManager;
+import mx.messaging.events.MessageEvent;
+import mx.messaging.messages.AsyncMessage;
+import mx.messaging.messages.IMessage;
+import mx.resources.IResourceManager;
+import mx.resources.ResourceManager;
+import mx.rpc.AbstractService;
+import mx.rpc.AsyncToken;
+import mx.rpc.AsyncDispatcher;
+import mx.rpc.Fault;
+import mx.rpc.events.FaultEvent;
+import mx.rpc.mxml.Concurrency;
+import mx.rpc.mxml.IMXMLSupport;
+import mx.rpc.soap.WebService;
+import mx.rpc.soap.Operation;
+import mx.rpc.soap.mxml.WebService;
+import mx.validators.Validator;
+
+use namespace mx_internal;
+
+//[ResourceBundle("rpc")]
+
+/**
+* An Operation used specifically by WebServices. An Operation is an individual method on a service. An Operation can be called either by invoking the function of the same name on the service or by accessing the Operation
+* as a property on the service and calling the <code>send()</code> method.
+*  
+*  @langversion 3.0
+*  @playerversion Flash 9
+*  @playerversion AIR 1.1
+*  @productversion Flex 3
+*/
+public class Operation extends mx.rpc.soap.Operation implements IMXMLSupport
+{
+    //--------------------------------------------------------------------------
+    //
+    // Constructor
+    // 
+    //--------------------------------------------------------------------------
+
+     /**
+      * Creates a new Operation. 
+      *
+      * @param webService The web service upon which this Operation is invoked.
+      *
+      * @param name The name of this Operation.
+      *  
+      *  @langversion 3.0
+      *  @playerversion Flash 9
+      *  @playerversion AIR 1.1
+      *  @productversion Flex 3
+      */
+   public function Operation(webService:mx.rpc.soap.WebService = null, name:String = null)
+    {
+        super(webService, name);
+
+        this.webService = mx.rpc.soap.mxml.WebService(webService);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    private var resourceManager:IResourceManager =
+                                    ResourceManager.getInstance();
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    [Inspectable(enumeration="multiple,single,last", defaultValue="multiple", category="General")]
+    /**
+     * The concurrency for this Operation.  If it has not been explicitly set the setting from the WebService
+     * will be used.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get concurrency():String
+    {
+        if (_concurrencySet)
+        {
+            return _concurrency;
+        }
+        //else
+        return webService.concurrency;
+    }
+
+    /**
+     *  @private
+     */
+    public function set concurrency(c:String):void
+    {
+        _concurrency = c;
+        _concurrencySet = true;
+    }
+
+    override mx_internal function setService(ro:AbstractService):void
+    {
+        super.setService(ro);
+
+        webService = mx.rpc.soap.mxml.WebService(ro);
+    }
+
+
+    /**
+     * Whether this operation should show the busy cursor while it is executing.
+     * If it has not been explicitly set the setting from the WebService
+     * will be used.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get showBusyCursor():Boolean
+    {
+        if (_showBusyCursorSet)
+        {
+            return _showBusyCursor;
+        }
+        //else
+        return webService.showBusyCursor;
+    }
+
+    public function set showBusyCursor(sbc:Boolean):void
+    {
+        _showBusyCursor = sbc;
+        _showBusyCursorSet = true;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function cancel(id:String = null) : AsyncToken
+    {
+        if (showBusyCursor)
+        {
+            CursorManager.removeBusyCursor();
+        }
+        return super.cancel(id);
+    }
+
+    /**
+     * @private
+     */
+    override public function send(... args:Array):AsyncToken
+    {
+        if (Concurrency.SINGLE == concurrency && (hasPendingInvocations() || activeCalls.hasActiveCalls()))
+        {
+            var token:AsyncToken = new AsyncToken(null);
+            var message:String = /*resourceManager.getString(
+                "rpc", */"pendingCallExists"/*);*/
+            var fault:Fault = new Fault("ConcurrencyError", message);
+            var faultEvent:FaultEvent = FaultEvent.createEvent(fault, token);
+            new AsyncDispatcher(dispatchRpcEvent, [faultEvent], 10);
+            return token;
+        }
+
+        return super.send.apply(null, args);
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Internal Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * @private
+     * Return the id for the NetworkMonitor
+     */
+    override mx_internal function getNetmonId():String
+    {
+        return webService.id;
+    }
+    
+
+    override mx_internal function invoke(message:IMessage, token:AsyncToken = null):AsyncToken
+    {
+        if (showBusyCursor)
+        {
+            CursorManager.setBusyCursor();
+        }
+
+        return super.invoke(message, token);
+    }
+
+    /*
+     * Kill the busy cursor, find the matching call object and pass it back
+     */
+    override mx_internal function preHandle(event:MessageEvent):AsyncToken
+    {
+        if (showBusyCursor)
+        {
+            CursorManager.removeBusyCursor();
+        }
+
+        var wasLastCall:Boolean = activeCalls.wasLastCall(AsyncMessage(event.message).correlationId);
+        var token:AsyncToken = super.preHandle(event);
+
+        if (Concurrency.LAST == concurrency && !wasLastCall)
+        {
+            return null;
+        }
+        //else
+        return token;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    private var _concurrency:String;
+    
+    private var _concurrencySet:Boolean;
+    
+    private var webService:mx.rpc.soap.mxml.WebService;
+    
+    private var _showBusyCursor:Boolean;
+    
+    private var _showBusyCursorSet:Boolean;
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/mxml/WebService.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/mxml/WebService.as
new file mode 100644
index 0000000..56d6bd0
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/mxml/WebService.as
@@ -0,0 +1,376 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap.mxml
+{
+
+import org.apache.royale.events.Event;
+import mx.events.ErrorEvent;
+import org.apache.royale.events.IEventDispatcher;
+
+import mx.core.IMXMLObject;
+import mx.core.mx_internal;
+import mx.resources.IResourceManager;
+import mx.resources.ResourceManager;
+import mx.rpc.AbstractOperation;
+import mx.rpc.events.FaultEvent;
+import mx.rpc.mxml.Concurrency;
+import mx.rpc.mxml.IMXMLSupport;
+import mx.rpc.soap.mxml.Operation;
+import mx.rpc.soap.WebService;
+
+use namespace mx_internal;
+
+[ResourceBundle("rpc")]
+
+/**
+ * The &lt;mx:WebService&gt; tag gives you access to the operations of SOAP-compliant
+ * web services.
+ * @mxml 
+ * <p>
+ * The &lt;mx:WebService&gt; tag accepts the following tag attributes:
+ * </p>
+ * <pre>
+ * &lt;mx:WebService
+ *   <b>Properties</b>
+ *   concurrency="multiple|single|last"
+ *   destination="<i>No default.</i>"
+ *   id="<i>No default.</i>"
+ *   serviceName="<i>No default.</i>"
+ *   showBusyCursor="false|true"
+ *   makeObjectsBindable="false|true"
+ *   useProxy="false|true"
+ *   wsdl="<i>No default.</i>"
+ *
+ *   <b>Events</b>
+ *   fault="<i>No default.</i>"
+ *   result="<i>No default.</i>"
+ * /&gt;
+ * </pre>
+ * </p>
+ * <p>
+ * An &lt;mx:WebService&gt; tag can have multiple &lt;mx:operation&gt; tags, which have the following tag attributes:
+ * </p>
+ * <pre>
+ * &lt;mx:operation
+ *   <b>Properties</b>
+ *   concurrency="multiple|single|last"
+ *   name=<i>No default, required.</i>
+ *   resultFormat="object|xml|e4x"
+ *   makeObjectsBindable="false|true"
+ *
+ *   
+ *   <b>Events</b>
+ *   fault=<i>No default.</i>
+ *   result=<i>No default.</i>
+ * /&gt;
+ * </pre>
+ *
+ * An &lt;mx:Operation&gt; tag contains an &lt;mx:request&gt; tag. 
+ * To specify an XML structure in an &lt;mx:request&gt; tag, you must set the value of the tag's
+ * <code>format</code> attribute to <code>"xml"</code>. Otherwise, the body is converted into Objects.
+ *
+ *  @includeExample examples/WebServiceExample.mxml -noswf
+ *
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public dynamic class WebService extends mx.rpc.soap.WebService implements IMXMLSupport, IMXMLObject
+{
+    //--------------------------------------------------------------------------
+    //
+    // Constructor
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Creates a new WebService component.
+     *
+     * @param destination The destination of the WebService, which should
+     * match a destination name in the services-config.xml file. If
+     * unspecified, the WebService component uses the DefaultHTTP destination.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function WebService(destination:String = null)
+    {
+        super(destination);
+
+        concurrency = Concurrency.MULTIPLE;
+        showBusyCursor = false;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    private var resourceManager:IResourceManager =
+									ResourceManager.getInstance();
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    [Inspectable(enumeration="multiple,single,last", defaultValue="multiple", category="General")]
+    /**
+     * Value that indicates how to handle multiple calls to the same service. The default
+     * value is multiple. The following values are permitted:
+     * <ul>
+     * <li>multiple - Existing requests are not cancelled, and the developer is
+     * responsible for ensuring the consistency of returned data by carefully
+     * managing the event stream. This is the default.</li>
+     * <li>single - Making only one request at a time is allowed on the method; additional requests made 
+     * while a request is outstanding are immediately faulted on the client and are not sent to the server.</li>
+     * <li>last - Making a request causes the client to ignore a result or fault for any current outstanding request. 
+     * Only the result or fault for the most recent request will be dispatched on the client. 
+     * This may simplify event handling in the client application, but care should be taken to only use 
+     * this mode when results or faults for requests may be safely ignored.</li>
+     * </ul>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get concurrency():String
+    {
+        return _concurrency;
+    }
+
+    /**
+     *  @private
+     */
+    public function set concurrency(c:String):void
+    {
+        _concurrency = c;
+    }
+
+    /**
+     * Deprecated, use the appropriate destination instead, or if using a url, use <code>DefaultHTTP</code> or <code>DefaultHTTPS</code>.
+     * The deprecated behavior will simply update the destination if the default is being used.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    [Deprecated(replacement="channelSet")]
+    public function set protocol(protocol:String):void
+    {
+        if (destination == DEFAULT_DESTINATION_HTTP || destination == DEFAULT_DESTINATION_HTTP)
+        {
+            if (protocol == "http")
+            {
+                destination = DEFAULT_DESTINATION_HTTP;
+            }
+            else if (protocol == "https")
+            {
+                destination = DEFAULT_DESTINATION_HTTPS;
+            }
+            else
+            {
+				var message:String = resourceManager.getString(
+					"rpc", "unknownProtocol", [ protocol ]);
+                throw new Error(message);
+            }
+        }
+    }
+
+    [Deprecated(replacement="destination")]
+    public function get serviceName():String
+    {
+        return destination;
+    }
+
+    public function set serviceName(sn:String):void
+    {
+        destination = sn;
+    }
+
+    [Inspectable(defaultValue="false", category="General")]
+ 
+    /**
+    * If <code>true</code>, a busy cursor is displayed while a service is executing. The default
+    * value is <code>false</code>.
+    *  
+    *  @langversion 3.0
+    *  @playerversion Flash 9
+    *  @playerversion AIR 1.1
+    *  @productversion Flex 3
+    */
+    public function get showBusyCursor():Boolean
+    {
+        return _showBusyCursor;
+    }
+
+    public function set showBusyCursor(sbc:Boolean):void
+    {
+        _showBusyCursor = sbc;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * This handler is called after the document fires the creationComplete event so that
+     * if errors occur while loading the WSDL all components will be ready to handle the fault.
+     * @private
+     */
+    public function creationComplete(event:Event):void
+    {
+        if (canLoadWSDL())
+        {
+            loadWSDL();
+        }
+    }
+
+    /**
+     * If this event is an error or fault, and the event type does not
+     * have a listener, we notify the parent document.  If the     
+     * parent document does not have a listener, then we throw
+     * a runtime exception.  However, this is an asynchronous runtime
+     * exception which is only exposed through the debug player.
+     * A listener should be defined.
+     *
+     * @private
+     */
+    override public function dispatchEvent(event:Event):Boolean
+    {
+        if (hasEventListener(event.type))
+        {
+            return super.dispatchEvent(event);
+        }
+        else if ((event is FaultEvent && !hasTokenResponders(event)) || event is ErrorEvent)
+        {
+            var reason:String = (event is FaultEvent) ?
+                FaultEvent(event).fault.faultString :
+                ErrorEvent(event).text;
+
+            if (document && document.willTrigger(ErrorEvent.ERROR))
+            {
+                var evt:ErrorEvent = new ErrorEvent(ErrorEvent.ERROR, true, true);
+                evt.text = reason;
+                return document.dispatchEvent(evt);
+            }
+            else if (event is FaultEvent)
+            {
+                throw FaultEvent(event).fault;
+            }
+            else
+            {
+				var message:String = resourceManager.getString(
+					"rpc", "noListenerForEvent", [ reason ]);
+                throw new Error(message);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns an Operation of the given name. If the Operation wasn't
+     * created beforehand, a new <code>mx.rpc.soap.mxml.Operation</code> is
+     * created during this call. Operations are usually accessible by simply
+     * naming them after the service variable
+     * (<code>myService.someOperation</code>), but if your Operation name
+     * happens to match a defined method on the service
+     * (like <code>setCredentials</code>), you can use this method to get the
+     * Operation instead.
+     * @param name Name of the Operation.
+     * @return Operation that executes for this name.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function getOperation(name:String):AbstractOperation
+    {
+        var o:Object = _operations[name];
+        var op:AbstractOperation = (o is AbstractOperation) ? AbstractOperation(o) : null;
+        if (op == null)
+        {
+            op = new Operation(this, name);
+            _operations[name] = op;
+            op.asyncRequest = asyncRequest;
+            op.setKeepLastResultIfNotSet(_keepLastResult);
+            initializeOperation(op as Operation);
+        }
+        return op;
+    }
+
+    /**
+     * Called automatically by the MXML compiler if the WebService is setup using a tag.  If you create
+     * the WebService through ActionScript you may want to call this method yourself as it is useful for
+     * validating any arguments.
+     *
+     * @param document the MXML document on which this WebService lives
+     * @param id the id of this WebService within the document
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function initialized(document:Object, id:String):void
+    {
+        this.document = document;
+        this.id = id;
+        if (document is IEventDispatcher)
+        {
+            IEventDispatcher(document).addEventListener("creationComplete", creationComplete);
+        }
+
+        initialize();
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    mx_internal var document:Object;
+    
+	mx_internal var id:String;
+    
+	private var _concurrency:String;
+    
+	private var _showBusyCursor:Boolean;
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/ApacheDocumentType.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/ApacheDocumentType.as
new file mode 100644
index 0000000..399e092
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/ApacheDocumentType.as
@@ -0,0 +1,55 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap.types
+{
+    
+import mx.rpc.soap.SOAPDecoder;
+import mx.rpc.soap.SOAPEncoder;
+import mx.rpc.xml.ContentProxy;
+import mx.utils.object_proxy;
+import mx.utils.ObjectProxy;
+
+use namespace object_proxy;
+
+[ExcludeClass]
+
+/**
+ * Marshalls between an Apache SOAP Document type and ActionScript XML.
+ * @private
+ */
+public class ApacheDocumentType implements ICustomSOAPType
+{
+    public function ApacheDocumentType()
+    {
+        super();
+    }
+
+    public function encode(encoder:SOAPEncoder, parent:XML, name:QName, value:*, restriction:XML = null):void
+    {
+    	encoder.setValue(parent, value);
+    }
+
+    public function decode(decoder:SOAPDecoder, parent:*, name:*, value:*, restriction:XML = null):void
+    {
+        decoder.setValue(parent, name, XML(value).elements());
+    }
+       
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/DataSetType.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/DataSetType.as
new file mode 100644
index 0000000..060004a
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/DataSetType.as
@@ -0,0 +1,165 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap.types
+{
+    
+import mx.rpc.soap.SOAPConstants;
+import mx.rpc.soap.SOAPDecoder;
+import mx.rpc.soap.SOAPEncoder;
+import mx.rpc.xml.ContentProxy;
+import mx.rpc.xml.Schema;
+import mx.rpc.xml.SchemaConstants;
+import mx.rpc.xml.TypeIterator;
+import mx.rpc.xml.XMLDecoder;
+import mx.utils.ObjectProxy;
+import mx.utils.object_proxy;
+
+use namespace object_proxy;
+
+[ExcludeClass]
+
+/**
+ * Marshalls between a .NET DataSet diffgram and ActionScript.
+ * @private
+ */
+public class DataSetType implements ICustomSOAPType
+{
+    public function DataSetType()
+    {
+        super();
+    }
+
+    public function encode(encoder:SOAPEncoder, parent:XML, name:QName, value:*, restriction:XML = null):void
+    {
+        throw new Error("Unsupported operation - .NET DataSet diffgrams cannot be sent from client.");
+    }
+
+    /**
+     * Decode a response part that contains a serialized DataSet.
+     * 
+     * @param SOAPDecoder the decoder instance
+     * @param * parent object (content proxy)
+     * @param name ignored
+     * @param value the top level XML node. Must have two child elements, schema and diffgram.
+     * @param restriction ignored
+     * 
+     * @private
+     */
+    public function decode(decoder:SOAPDecoder, parent:*, name:*, value:*, restriction:XML = null):void
+    {
+        if (parent is ContentProxy)
+            ContentProxy(parent).object_proxy::isSimple = false;
+
+        schemaConstants = decoder.schemaConstants;
+
+        var schemaXML:XML = XML(value).elements(schemaConstants.schemaQName)[0];
+
+        //TODO: handle <diffgr:before> and <diffgr:errors>
+        var rootDataXML:XML = XML(value).elements(SOAPConstants.diffgramQName)[0].elements()[0];
+        var dataSet:* = parent;
+        var tableDefinitions:Object = processTables(schemaXML);
+
+        // First create .Tables and .Columns and .Rows for each table
+        var tableCollection:* = decoder.createContent();
+        if (tableCollection is ContentProxy)
+                ContentProxy(tableCollection).object_proxy::isSimple = false;
+        
+        for (var tblName:String in tableDefinitions)
+        {
+            var tableObj:* = decoder.createContent();
+            if (tableObj is ContentProxy)
+                ContentProxy(tableObj).object_proxy::isSimple = false;
+            decoder.setValue(tableObj, "Columns",
+                            processColumns(decoder, tableDefinitions[tblName]));
+            decoder.setValue(tableObj, "Rows",
+                            decoder.createIterableValue());
+            decoder.setValue(tableCollection, tblName, tableObj);
+        }
+        
+        if (rootDataXML != null)
+        {
+            var schema:Schema = new Schema(schemaXML);
+            decoder.schemaManager.addSchema(schema, false);
+            
+            for (tblName in tableCollection)
+            {
+                for each (var rowXML:XML in rootDataXML.elements(tblName))
+                {
+                    var rowObj:* = decoder.decode(rowXML, rowXML.name() as QName, null, tableDefinitions[tblName]);
+                    TypeIterator.push(tableCollection[tblName]["Rows"], rowObj);
+                }
+            }
+
+            decoder.schemaManager.releaseScope();
+        }
+
+        decoder.setValue(dataSet, "Tables", tableCollection);
+    }
+    
+    /**
+     * Parse table information out of the inline schema
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function processTables(schemaXML:XML):Object
+    {
+        // The table definitions are elements inside a choice inside
+        // a complexType inside a top-level element in the schema
+        var tblsXMLList:XMLList = schemaXML.elements(schemaConstants.elementTypeQName)[0]
+                .elements(schemaConstants.complexTypeQName)[0]
+                .elements(schemaConstants.choiceQName)[0]
+                .elements(schemaConstants.elementTypeQName);
+        
+        var tables:Object = {};
+        for each (var tblXML:XML in tblsXMLList)
+            tables[tblXML.attribute("name")] = tblXML;
+
+        return tables;
+    }
+    
+    /**
+     * Parse column definitions out of a table definition
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function processColumns(decoder:SOAPDecoder, tableXML:XML):*
+    {
+        // The column definitions are elements inside a sequence inside
+        // a complexType in the table definition element.
+        var colsXMLList:XMLList = tableXML.elements(schemaConstants.complexTypeQName)[0]
+                .elements(schemaConstants.sequenceQName)[0]
+                .elements(schemaConstants.elementTypeQName);
+        
+        var columns:* = decoder.createIterableValue();
+        for each (var colXML:XML in colsXMLList)
+            TypeIterator.push(columns, colXML.attribute("name").toString());
+            
+        return columns;
+    }
+    
+    private var schemaConstants:SchemaConstants;
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/ICustomSOAPType.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/ICustomSOAPType.as
new file mode 100644
index 0000000..d43fe16
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/ICustomSOAPType.as
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap.types
+{
+
+import mx.rpc.soap.SOAPDecoder;
+import mx.rpc.soap.SOAPEncoder;
+
+[ExcludeClass]
+
+/**
+ * Implementations handle encoding and decoding between custom SOAP types and 
+ * ActionScript.
+ * 
+ * @private
+ */
+public interface ICustomSOAPType
+{
+    function encode(encoder:SOAPEncoder, parent:XML, name:QName, value:*, restriction:XML = null):void;
+
+    function decode(decoder:SOAPDecoder, parent:*, name:*, value:*, restriction:XML = null):void;
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/MapType.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/MapType.as
new file mode 100644
index 0000000..65a0198
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/MapType.as
@@ -0,0 +1,168 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap.types
+{
+
+import mx.utils.ByteArray;
+
+import mx.rpc.soap.SOAPDecoder;
+import mx.rpc.soap.SOAPEncoder;
+import mx.rpc.xml.ContentProxy;
+import mx.rpc.xml.SchemaConstants;
+import mx.rpc.xml.SchemaDatatypes;
+import mx.rpc.xml.SchemaMarshaller;
+import mx.utils.object_proxy;
+
+use namespace object_proxy;
+
+[ExcludeClass]
+
+/**
+ * Marshalls between the SOAP representation of a java.util.Map and
+ * ActionScript.
+ * @private
+ */
+public class MapType implements ICustomSOAPType
+{
+    public function MapType()
+    {
+        super();
+    }
+
+    public function encode(encoder:SOAPEncoder, parent:XML, name:QName, value:*, restriction:XML = null):void
+    {
+        var datatypes:SchemaDatatypes = encoder.schemaManager.schemaDatatypes;
+
+        for (var item:String in value)
+        {
+            var itemNode:XML = encoder.createElement(itemQName);
+            var keyNode:XML = encoder.createElement(keyQName);
+            var valueNode:XML = encoder.createElement(valueQName);
+
+            // TODO: a better solution is needed for both key and value processing here...
+            if (item != null)
+                encoder.encodeType(datatypes.stringQName, keyNode, keyQName, item);
+            else
+                encoder.setValue(keyNode, null);
+
+            encoder.setValue(itemNode, keyNode);
+
+            //FIXME: We need a public API to handle any, even complex values
+            var keyValue:Object = value[item];
+            if (keyValue != null)
+            {
+                // FIXME: completely.
+                var typeLocalName:String = "string";
+                if (keyValue is Number)
+                {
+                    if (keyValue is uint)
+                    {
+                        typeLocalName = "unsignedInt";
+                    }
+                    else if (keyValue is int)
+                    {
+                        typeLocalName = "int";
+                    }
+                    else
+                    {
+                        typeLocalName = "double";
+                    }
+                }
+                else if (keyValue is Boolean)
+                {
+                    typeLocalName = "boolean";
+                }
+                else if (keyValue is String)
+                {
+                    typeLocalName = "string";
+                }
+                else if (keyValue is ByteArray)
+                {
+                    if (SchemaMarshaller.byteArrayAsBase64Binary)
+                        typeLocalName = "base64Binary";
+                    else
+                        typeLocalName = "hexBinary";
+                }
+                else if (keyValue is Date)
+                {
+                    typeLocalName = "dateTime";
+                }
+
+                var constants:SchemaConstants = encoder.schemaManager.schemaConstants;
+                var type:QName = (typeLocalName != null) ? new QName(constants.xsdURI, typeLocalName) : null;
+
+                encoder.encodeType(type, valueNode, valueQName, keyValue);
+            }
+            else
+            {
+                encoder.setValue(valueNode, null);
+            }
+
+            encoder.setValue(itemNode, valueNode);
+            encoder.setValue(parent, itemNode);
+        }
+    }
+
+    public function decode(decoder:SOAPDecoder, parent:*, name:*, value:*, restriction:XML = null):void
+    {
+        if (parent is ContentProxy)
+            parent.object_proxy::isSimple = false;
+
+        var constants:SchemaConstants = decoder.schemaManager.schemaConstants;
+        var mapValue:XML = value as XML;
+
+        for each (var item:XML in mapValue.elements())
+        {
+            var key:Object;
+            var itemValue:Object;
+            for each (var itemChild:XML in item.elements())
+            {
+                var typeName:String = itemChild.attribute(constants.typeAttrQName);
+                var type:QName;
+                if (typeName != null && typeName != "")
+                    type = decoder.schemaManager.getQNameForPrefixedName(typeName, itemChild);
+                else
+                    type = constants.anyTypeQName;
+
+                if (itemChild.localName() == "key")
+                {
+                    key = decoder.createContent();
+                    decoder.decodeType(type, key, itemChild.name() as QName, itemChild);
+                }
+                else if (itemChild.localName() == "value")
+                {
+                    itemValue = decoder.createContent();
+                    decoder.decodeType(type, itemValue, itemChild.name() as QName, itemChild);
+                }
+                else
+                {
+                    throw new Error("Apache Map datatype must only contain key/value pairs.");
+                }
+            }
+            decoder.setValue(parent, key, itemValue);
+        }
+    }
+
+    public static var itemQName:QName = new QName("", "item");
+    public static var keyQName:QName = new QName("", "key");
+    public static var valueQName:QName = new QName("", "value");
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/QueryBeanType.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/QueryBeanType.as
new file mode 100644
index 0000000..4343abc
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/QueryBeanType.as
@@ -0,0 +1,107 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap.types
+{
+
+import mx.rpc.soap.SOAPDecoder;
+import mx.rpc.soap.SOAPEncoder;
+import mx.rpc.xml.ContentProxy;
+import mx.rpc.xml.TypeIterator;
+import mx.rpc.xml.XMLDecoder;
+import mx.utils.object_proxy;
+import mx.utils.ObjectProxy;
+
+use namespace object_proxy;
+
+[ExcludeClass]
+
+/**
+ * Marshalls between the SOAP representation of a ColdFusion Query (aka a
+ * "Query Bean") and ActionScript.
+ * @private
+ */
+public class QueryBeanType implements ICustomSOAPType
+{
+    public function QueryBeanType()
+    {
+        super();
+    }
+
+    public function encode(encoder:SOAPEncoder, parent:XML, name:QName, value:*, restriction:XML = null):void
+    {
+        throw new Error("Unsupported operation - Query Beans cannot be sent to ColdFusion.");
+    }
+
+    public function decode(decoder:SOAPDecoder, parent:*, name:*, value:*, restriction:XML = null):void
+    {
+        var beanXML:XML = value as XML;
+        
+        var returnVal:*;
+        if (decoder.makeObjectsBindable)
+            returnVal = new XMLDecoder.listClass();
+        else
+            returnVal = [];
+
+        // Query Column Names or "columnList" section
+        var colXML:XML = beanXML.columnList[0];
+        if (colXML == null)
+            return;
+
+        var columnsXMLList:XMLList = colXML.elements();
+        var columnNames:Array = [];
+        for each (var columnName:XML in columnsXMLList)
+        {
+            columnNames.push(columnName.toString());
+        }
+
+        // Query Rows or "data" section
+        var dataXML:XML = beanXML.data[0];
+        if (dataXML == null)
+            return;
+
+        var soapArrayType:SOAPArrayType = new SOAPArrayType();
+        var tempParent:Array = [];
+        soapArrayType.decode(decoder, tempParent, name, dataXML, restriction);
+
+        // Turn the Array of Arrays into an Array of Objects keyed by a
+        // column name to value...
+        var iterator:TypeIterator = new TypeIterator(tempParent);
+        while (iterator.hasNext())
+        {
+            var item:* = iterator.next();
+            var resultItem:*;
+            if (decoder.makeObjectsBindable)
+                resultItem = new ObjectProxy();
+            else
+                resultItem = {};
+
+            for (var i:uint = 0; i < columnNames.length; i++)
+            {
+                resultItem[columnNames[i]] = item[i];
+            }
+
+            TypeIterator.push(returnVal, resultItem);
+        }
+
+        decoder.setValue(parent, name, returnVal);
+    }
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/RowSetType.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/RowSetType.as
new file mode 100644
index 0000000..fcbcf1d
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/RowSetType.as
@@ -0,0 +1,119 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap.types
+{
+
+import mx.rpc.soap.SOAPDecoder;
+import mx.rpc.soap.SOAPEncoder;
+import mx.rpc.xml.ContentProxy;
+import mx.rpc.xml.TypeIterator;
+import mx.utils.object_proxy;
+
+use namespace object_proxy;
+
+[ExcludeClass]
+
+/**
+ * Marshalls between the SOAP representation of a ColdFusion Query (aka a
+ * "Query Bean") and ActionScript.
+ * @private
+ */
+public class RowSetType implements ICustomSOAPType
+{
+    public function RowSetType()
+    {
+        super();
+    }
+
+    public function encode(encoder:SOAPEncoder, parent:XML, name:QName, value:*, restriction:XML = null):void
+    {
+        throw new Error("Unsupported operation - RowSet cannot be sent to a server.");
+    }
+
+    // Custom deserialization for rowsets, which look like this:
+    //
+    // <rowSet>
+    //   <fields>
+    //     <field type="xsd:string">Field1</field>
+    //     <field type="xsd:int">Field2</field>
+    //   </fields>
+    //   <data>
+    //    <item>
+    //     <d>a string</d>
+    //     <d>52</d>
+    //    </item>
+    //   </data>
+    // </rowSet>
+    //
+    // (That would decode into an Array with a single object {Field1:"a string", Field2:52})
+    //
+    public function decode(decoder:SOAPDecoder, parent:*, name:*, value:*, restriction:XML = null):void
+    {
+        if (parent is ContentProxy)
+            parent.object_proxy::isSimple = false;
+
+        var rowSetNode:XML = value as XML;
+
+        var returnVal:Array = [];
+        var types:Array = [];
+        var fields:Array = [];
+
+        var fieldNodes:XMLList = rowSetNode.elements()[0].elements();
+        var i:uint;
+
+        // Gather each of the field names and types
+        for each (var field:XML in fieldNodes)
+        {
+            var typeAttr:String = field.attribute("type").toString();
+            var typeQName:QName;
+
+            if (typeAttr != null && typeAttr != "")
+                typeQName = decoder.schemaManager.getQNameForPrefixedName(typeAttr, field);
+
+            if (typeQName == null)
+                typeQName = decoder.schemaManager.schemaDatatypes.stringQName;
+
+            types[i] = typeQName;
+            fields[i] = field.text().toString();
+            i++;
+        }
+
+        var items:XMLList = rowSetNode.elements()[1].elements();
+
+        // Process each Row using field names and types
+        i = 0;
+        for each (var item:XML in items)
+        {
+            var columns:XMLList = item.elements();
+            var row:* = decoder.createContent();
+            var j:uint = 0;
+            for each (var column:XML in columns)
+            {
+                row[fields[j]] = decoder.decode(column, null, types[j] as QName);
+                j++;
+            }
+            returnVal[i] = row;
+            i++;
+        }
+
+        decoder.setValue(parent, name, returnVal);
+    }
+}
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/SOAPArrayType.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/SOAPArrayType.as
new file mode 100644
index 0000000..ccad810
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/soap/types/SOAPArrayType.as
@@ -0,0 +1,614 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.soap.types
+{
+
+import mx.collections.IList;
+import mx.rpc.soap.SOAPConstants;
+import mx.rpc.soap.SOAPEncoder;
+import mx.rpc.soap.SOAPDecoder;
+import mx.rpc.wsdl.WSDLConstants;
+import mx.rpc.xml.ContentProxy;
+import mx.rpc.xml.SchemaConstants;
+import mx.rpc.xml.SchemaDatatypes;
+import mx.rpc.xml.SchemaManager;
+import mx.rpc.xml.SchemaMarshaller;
+import mx.rpc.xml.SchemaProcessor;
+import mx.rpc.xml.TypeIterator;
+import mx.rpc.xml.XMLEncoder;
+import mx.rpc.xml.XMLDecoder;
+import mx.utils.object_proxy;
+import mx.utils.StringUtil;
+import mx.utils.ObjectUtil;
+
+use namespace object_proxy;
+
+[ExcludeClass]
+
+/**
+ * Marshalls SOAP 1.1 encoded Arrays between XML and ActionScript.
+ * @private
+ */
+public class SOAPArrayType implements ICustomSOAPType
+{
+    public function SOAPArrayType()
+    {
+        super();
+        itemName = new QName("", "item");                            
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Encode an ActionScript Array as a SOAP encoded Array in XML.
+     * 
+     * TODO: Support soap array offset and item position attributes?
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function encode(encoder:SOAPEncoder, parent:XML, name:QName, value:*, restriction:XML = null):void
+    {
+        processor = encoder;
+        soapConstants = encoder.soapConstants;
+        schemaManager = encoder.schemaManager;
+        schemaConstants = schemaManager.schemaConstants;
+
+        // HACK: Handle the MXML artifact where by <mx:request> based syntax
+        // for SOAP parameters can lead to Arrays of properties being wrapped
+        // in an Object with a single property with the Array as its value.
+        value = unwrapMXMLArray(value);
+
+        // FIXME: Should we look in the restriction definition to see
+        // if a sequence was provided to define the element name? The
+        // SOAPArrayEncoder will just assume "item" for now...
+
+        if (restriction != null)
+        {
+            // Look for arrayType under <restriction base="soap-enc:Array">
+            var wsdlArrayType:String = determineWSDLArrayType(restriction, encoder.wsdlOperation.wsdlConstants);
+
+            // Parse the arrayType looking for XML Schema type, dimensions and size info
+            parseWSDLArrayType(wsdlArrayType);
+        }
+
+        schemaType = schemaManager.getQNameForPrefixedName(schemaTypeName, restriction);
+
+        // Ensure SOAP encoding namespace has been declared
+        // e.g. <myArray xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
+        parent.addNamespace(soapConstants.encodingNamespace);
+
+        // Add SOAP encoding arrayType attribute for parent node
+        // e.g. <myArray soapenc:arrayType="xsd:int[][3]">
+        encodeDimensionInformation(parent, dimensionString);
+        encodeArray(parent, dimensions, value);
+    }
+
+    /**
+     * Decodes a SOAP encoded array assuming the XML Schema type definiton
+     * uses a complexType restriction base to declare the array type, e.g.
+     * 
+     * <pre>
+     * &lt;xsd:complexType name="Example"&gt;
+     *   &lt;xsd:complexContent mixed="false"&gt;
+     *     &lt;xsd:restriction base="soapenc:Array"&gt;
+     *       &lt;xsd:attribute wsdl:arrayType="tns:Example[]" ref="soapenc:arrayType" 
+     *           xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" /&gt;
+     *      &lt;/xsd:restriction&gt;
+     *   &lt;/xsd:complexContent&gt;
+     * &lt;/xsd:complexType&gt;
+     * </pre>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function decode(decoder:SOAPDecoder, parent:*, name:*, value:*, restriction:XML = null):void
+    {
+        processor = decoder;
+        soapConstants = decoder.soapConstants;
+        schemaManager = decoder.schemaManager;
+        schemaConstants = schemaManager.schemaConstants;
+
+        // Handle short-hand syntax for SOAP encoded arrayType
+        var valueXML:XML = value as XML;
+        if (valueXML != null)
+        {
+            var arrayTypeString:String = valueXML.@[soapConstants.soapencArrayTypeQName];
+            if (arrayTypeString != null && arrayTypeString != "")
+            {
+                parseWSDLArrayType(arrayTypeString);
+                schemaType = schemaManager.getQNameForPrefixedName(schemaTypeName, valueXML);
+            }
+        }
+
+        // Otherwise look for arrayType under <restriction base="soap-enc:Array">
+        if (schemaType == null && restriction != null)
+        {
+            var wsdlArrayType:String = determineWSDLArrayType(restriction, decoder.wsdlOperation.wsdlConstants);
+            parseWSDLArrayType(wsdlArrayType);
+            schemaType = schemaManager.getQNameForPrefixedName(schemaTypeName, restriction);
+        }
+
+        if (schemaType != null)
+        {
+            // Change the parent to an Array. Parent is originally created with
+            // createContent in the XMLDecoder, before decodeType is called. We
+            // need to make sure that the created parent can be used as an array.
+
+            if (parent is ContentProxy)
+            {
+                var proxy:ContentProxy = parent as ContentProxy;
+                proxy.object_proxy::isSimple = false;
+                // Only replace parent with iterable value if not already an IList
+                // or an Array.
+                if (!(proxy.object_proxy::content is IList) && !(proxy.object_proxy::content is Array))
+                    proxy.object_proxy::content = decoder.createIterableValue();
+            }
+
+            decodeArray(parent, dimensions, value, decoder.makeObjectsBindable);
+        }
+    }
+
+    /**
+     * Recursively called to encode a set of dimensions at a particular level
+     * (potentially many of a jagged/nested array) of an Array.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function encodeArray(parent:XML, dimensions:Array, value:*):void
+    {
+        // Add XSI attribute for SOAP encoded Array
+        // e.g. <myArray xsi:type="soapenc:Array" />
+        var typeAttr:String = schemaConstants.getXSIToken(schemaConstants.typeAttrQName)
+        parent.@[typeAttr] = soapConstants.getSOAPEncodingToken(soapConstants.soapencArrayQName);
+
+        if (!TypeIterator.isIterable(value))
+            value = [value];
+
+        var iter:TypeIterator = new TypeIterator(value);
+        var d:uint = 0;
+        
+        if (dimensions.length > 0)
+        {
+            // For a non-jagged Array we have a single entry that describes the
+            // length of each dimension (which can be unbounded), otherwise
+            // we have multiple entries, but the first is used to describe
+            // the number of jagged arrays at this level...
+            var entry:* = dimensions[0];
+            if (!(entry is Array))
+                entry = [entry];
+
+            for each (var dimensionSize:int in entry)
+            {
+                var itemValue:*;
+                var nestedDimension:Array;
+                var nestedDimensionString:String;
+                var nestedArray:XML;
+                d++;
+                
+                if (dimensionSize < 0)
+                {
+                    // Unbounded dimension
+                    if (dimensions.length == 1)
+                    {
+                        while (iter.hasNext())
+                        {
+                            itemValue = iter.next();
+                            nestedArray = <{itemName.localName}/>;
+                            encodeArrayItem(nestedArray, itemValue);
+                            parent.appendChild(nestedArray);
+                        }
+                    }
+                    else if (dimensions.length > 1)
+                    {
+                        nestedDimensionString = "[]";
+
+                        // FIXME: We should detect before iterating whether 
+                        // sufficient definitions exist for the number of
+                        // jagged arrays provided in the value...
+                        while (iter.hasNext())
+                        {
+                            itemValue = iter.next();
+                            nestedDimension = dimensions[d];
+                            nestedArray = <{itemName.localName}/>;
+                            encodeDimensionInformation(nestedArray, nestedDimensionString);
+                            encodeArray(nestedArray, nestedDimension, itemValue);
+                            parent.appendChild(nestedArray);
+                        }
+                    }
+                }
+                else
+                {
+                    // Bounded dimension
+                    for (var i:uint = 0; i < dimensionSize; i++)
+                    {
+                        itemValue = TypeIterator.getItemAt(iter.value, i);
+                        if (dimensions.length == 1)
+                        {
+                            nestedArray = <{itemName.localName}/>;
+                            encodeArrayItem(nestedArray, itemValue);
+                            parent.appendChild(nestedArray);
+                        }
+                        else if (dimensions.length > 1)
+                        {
+                            nestedDimensionString = "[" + dimensionSize + "]";
+
+                            // FIXME: We should detect invalid no. of nested
+                            // dimensions compared to value...
+                            nestedDimension = dimensions[d];
+                            nestedArray = <{itemName.localName}/>;
+                            encodeDimensionInformation(nestedArray, nestedDimensionString);
+                            encodeArray(nestedArray, nestedDimension, itemValue);
+                            parent.appendChild(nestedArray);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private function decodeArray(parent:*, dimensions:Array, value:*, makeObjectsBindable:Boolean):void
+    {
+        // If we have a single node, grab the XMLList of child elements as 
+        // the actual Array members...
+        if (value is XML)
+        {
+            var dataXML:XML = value as XML;
+            value = dataXML.elements();
+        }
+
+        if (!TypeIterator.isIterable(value) && value != "")
+            value = [value];
+
+        var iter:TypeIterator = new TypeIterator(value);
+        var d:uint = 0;
+
+        if (dimensions.length > 0)
+        {
+            // For a non-jagged Array we have a single entry that describes the
+            // length of each dimension (which can be unbounded), otherwise
+            // we have multiple entries, but the first is used to describe
+            // the number of jagged arrays at this level...
+            var entry:* = dimensions[0];
+            if (!(entry is Array))
+                entry = [entry];
+
+            for each (var dimensionSize:int in entry)
+            {
+                var itemValue:*;
+                var nestedDimension:Array;
+                var nestedArray:*;
+                d++;
+
+                if (dimensionSize < 0)
+                {
+                    // Unbounded dimension
+                    if (dimensions.length == 1)
+                    {
+                        while (iter.hasNext())
+                        {
+                            itemValue = iter.next();
+                            decodeArrayItem(parent, itemValue);
+                        }
+                    }
+                    else if (dimensions.length > 1)
+                    {
+                        // FIXME: We should detect before iterating whether 
+                        // sufficient definitions exist for the number of
+                        // jagged arrays provided in the value...
+                        while (iter.hasNext())
+                        {
+                            itemValue = iter.next();
+                            nestedDimension = dimensions[d];
+                            nestedArray = SOAPDecoder(processor).createIterableValue(schemaType);
+                            decodeArray(nestedArray, nestedDimension, itemValue, makeObjectsBindable);
+                            TypeIterator.push(parent, nestedArray);
+                        }
+                    }
+                }
+                else
+                {
+                    // Bounded dimension
+                    for (var i:uint = 0; i < dimensionSize; i++)
+                    {
+                        itemValue = TypeIterator.getItemAt(iter.value, i);
+                        if (dimensions.length == 1)
+                        {
+                            decodeArrayItem(parent, itemValue);
+                        }
+                        else if (dimensions.length > 1)
+                        {
+                            // FIXME: We should detect invalid no. of nested
+                            // dimensions compared to value...
+                            nestedDimension = dimensions[d];
+                            nestedArray = SOAPDecoder(processor).createIterableValue(schemaType);
+                            decodeArray(nestedArray, nestedDimension, itemValue, makeObjectsBindable);
+                            TypeIterator.push(parent, nestedArray);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    private function encodeArrayItem(item:XML, value:*):void
+    {
+        var encoder:SOAPEncoder = processor as SOAPEncoder;
+        encoder.encodeType(schemaType, item, itemName, value);
+    }
+    
+    private function  decodeArrayItem(parent:*, value:*):void
+    {
+        var decoder:SOAPDecoder = processor as SOAPDecoder;
+        var item:* = decoder.createContent(schemaType);
+        decoder.decodeType(schemaType, item, itemName, value);
+        decoder.setValue(parent, itemName, item, schemaType);
+    }
+
+    private function encodeDimensionInformation(parent:XML, dimensionString:String):void
+    {
+        var uri:String = schemaType.uri;
+        var prefix:String = schemaManager.getOrCreatePrefix(uri);
+        var ns:Namespace = new Namespace(prefix, uri);
+        var arrayTypeString:String = prefix + ":" + schemaType.localName;
+        arrayTypeString = arrayTypeString + dimensionString;
+        parent.addNamespace(ns);
+        var arrayTypeAttr:String = soapConstants.getSOAPEncodingToken(soapConstants.soapencArrayTypeQName);
+        parent.@[arrayTypeAttr] = arrayTypeString;
+    }
+
+    private function getSingleElementFromNode(node:XML, ...types:Array):XML
+    {
+        var elements:XMLList = node.elements();
+        for each (var element:XML in elements)
+        {
+            if (types != null && types.length > 0)
+            {
+                for each (var type:QName in types)
+                {
+                    if (element.name() == type)
+                    {
+                        return element;
+                    }
+                }
+            }
+            else
+            {
+                return element;
+            }
+        }
+        return null;
+    }
+
+    private function determineWSDLArrayType(restriction:XML, wsdlConstants:WSDLConstants):String
+    {
+        var arrayTypeString:String = "";
+
+        // We expect a <attribute ref="soap-enc:ArrayType"> in the restriction
+        var attribute:XML = getSingleElementFromNode(restriction, schemaConstants.attributeQName);
+        if (attribute != null)
+        {
+            // The attribute must declare that it is using the SOAP encoded Array
+            // type using a ref="soapenc:Array" attribute...
+            var soapencArrayTypeRef:String = attribute.@ref;
+            var soapencArrayType:QName = schemaManager.getQNameForPrefixedName(soapencArrayTypeRef, attribute, true);
+            if (soapencArrayType == soapConstants.soapencArrayTypeQName)
+            {
+                // Next, we look for wsdl:arrayType attribute
+                arrayTypeString = attribute.attribute(wsdlConstants.wsdlArrayTypeQName).toString();
+            }
+        }
+
+        return arrayTypeString;
+    }
+        
+
+    /**
+     * Parses the WSDL arrayType to determine the type of the members in a SOAP
+     * encoded array, the rank and dimensions of the Array, and potentially
+     * the size of the Array (if not unbounded).
+     * 
+     * TODO: Support SOAP 1.2 syntax for Arrays.
+     * 
+     * Examples:
+     * 1. An unbounded Array of strings:
+     * <xsd:attribute ref="soap-enc:arrayType" wsdl:arrayType="xsd:string[]" />
+     * 
+     * 2. An Array with 5 members of type "Array of integers":
+     * <xsd:attribute ref="soap-enc:arrayType" wsdl:arrayType="xsd:int[][5]" />
+     * 
+     * 3. An Array with 3 members of type "two-dimensional arrays of integers":
+     * <xsd:attribute ref="soap-enc:arrayType" wsdl:arrayType="xsd:int[,][3]" />
+     * 
+     * @param wsdlArrayType The value of the wsdl:arrayType attribute that
+     * specifies the signature of the SOAP encoded array including the type and
+     * the dimensions and size information.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parseWSDLArrayType(wsdlArrayType:String):void
+    {
+        // Isolate the prefixed schemaType from the rank and length information
+        // QName *(rank) size
+        var typeName:String;
+        var startBracket:int = wsdlArrayType.indexOf("[");
+        var endBracket:int = -1;
+
+        if (startBracket > 0)
+        {
+            dimensionString = wsdlArrayType.substring(startBracket);
+            schemaTypeName = StringUtil.trim(wsdlArrayType.substring(0, startBracket));
+            endBracket = wsdlArrayType.indexOf("]", startBracket);
+        }
+
+        if (startBracket < 0 || endBracket < 0)
+        {
+            throw new Error("Invalid SOAP-encoded Array type '" + wsdlArrayType + "'.");
+        }
+
+        var rankOrSizeString:String = StringUtil.trim(wsdlArrayType.substring(startBracket));
+        var dimsArray:Array = rankOrSizeString.split("[");
+        var currentDimension:Array = dimensions;
+
+        // We process the rank from right to left as the size of the type is the
+        // right most set of brackets. Jagged arrays are treated as a nested
+        // set of dimensions.
+        for (var i:int = dimsArray.length - 1; i >= 0; i--)
+        {
+            var dimsString:String = dimsArray[i] as String;
+
+            // We should have at the very least a close bracket
+            if (dimsString.length > 0)
+            {
+                // A rank may define none [], one [x], or multiple dimensions [x,y]
+                if (currentDimension.length > 0)
+                {
+                    var newDimension:Array = [];
+                    currentDimension.push(newDimension);
+                    currentDimension = newDimension;
+                }
+                parseDimensions(wsdlArrayType, dimsString, currentDimension);
+            }
+        }
+    }
+
+    private function parseDimensions(wsdlArrayType:String, dimensionsString:String, currentDimension:Array):void
+    {
+        // Remove leading or trailing braces from [x,y,...] to reveal x,y,...
+        if (dimensionsString.charAt(0) == "[")
+            dimensionsString = dimensionsString.substring(1);
+
+        if (dimensionsString.charAt(dimensionsString.length - 1) == "]")
+            dimensionsString = dimensionsString.substring(0, dimensionsString.length - 1);
+
+        var dim:Number;
+        var dimensions:Array = dimensionsString.split(",");
+        if (dimensions.length > 0)
+        {
+            // Process each dimension from x,y,... as "x" or "y" etc...
+            for each (var dimString:String in dimensions)
+            {
+                if (dimString.length > 0)
+                {
+                    dim = parseInt(dimString);
+                    if (!isNaN(dim) && dim < int.MAX_VALUE)
+                    {
+                        currentDimension.push(int(dim));
+                    }
+                    else
+                    {
+                        throw new Error("Invalid dimension '" + dimString + "' for SOAP encoded Array type '" + wsdlArrayType +"'.");
+                    }
+                }
+                else
+                {
+                    // Unbounded dimension, record as -1
+                    currentDimension.push(-1);
+                }
+            }
+        }
+    }
+
+    /**
+     * Attempts to unwrap MXML Array properties that are wrapped in an Object
+     * with a single child element that is an Array itself.
+     * 
+     * e.g. the following MXML:
+     * 
+     * <mx:request>
+     *     <inputArray>
+     *         <item>A</item>
+     *         <item>B</item>
+     *     </inputArray>
+     * </mx:request>
+     * 
+     * would return an Object for inputArray as {item:[A,B]} instead of
+     * simply the Array [A,B].
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function unwrapMXMLArray(value:*):*
+    {
+        var result:* = value;
+
+        if (!(value is Array))
+        {
+            try
+            {
+                var classInfo:Object = ObjectUtil.getClassInfo(value as Object);
+                var properties:Array = classInfo["properties"];
+                if (properties.length == 1)
+                {
+                    var property:String = properties[0];
+                    if (property != null && value.hasOwnProperty(property))
+                    {
+                        var childValue:* = value[property];
+                        if (childValue is Array)
+                        {
+                            result = childValue;
+                        }
+                    }
+                }
+            }
+            catch(e:Error)
+            {
+            }
+        }
+
+        return result;
+    }
+
+    private function get dimensions():Array
+    {
+        if (_dimensions == null)
+            _dimensions = [];
+
+        return _dimensions;
+    }
+
+    private var _dimensions:Array;
+    private var dimensionString:String;
+    private var itemName:QName;
+    private var processor:SchemaProcessor;
+    private var schemaConstants:SchemaConstants;
+    private var schemaManager:SchemaManager;
+    private var schemaTypeName:String;
+    private var schemaType:QName;
+    private var soapConstants:SOAPConstants;
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/wsdl/WSDL.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/wsdl/WSDL.as
new file mode 100644
index 0000000..b83cd85
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/wsdl/WSDL.as
@@ -0,0 +1,1366 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.wsdl
+{
+
+import mx.logging.ILogger;
+import mx.logging.Log;
+import mx.resources.IResourceManager;
+import mx.resources.ResourceManager;
+import mx.rpc.Fault;
+import mx.rpc.soap.SOAPConstants;
+import mx.rpc.xml.QualifiedResourceManager;
+import mx.rpc.xml.Schema;
+import mx.rpc.xml.SchemaConstants;
+import mx.rpc.xml.SchemaManager;
+import mx.rpc.xml.SchemaTypeRegistry;
+
+[ResourceBundle("rpc")]
+
+[ExcludeClass]
+
+/**
+ * Manages a WSDL top-level <code>definitions</code> element. WSDL definitions
+ * may contain imports to other WSDL definitions. Only SOAP bindings are
+ * supported.
+ * 
+ * @private
+ */
+public class WSDL
+{
+    //--------------------------------------------------------------------------
+    //
+    // Constructor
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * Constructs a WSDL from XML. Services and their operations are
+     * parsed into object representations on the first call to
+     * <code>getService()</code>, <code>getPort()</code> or
+     * <code>getOperation()</code>.
+     *
+     * @param xml An XML document starting from the top-level WSDL 
+     * <code>defintions</code> element.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function WSDL(xml:XML, topLevelManager:SchemaManager=null)
+    {
+        super();
+        
+        // Fix for SDK-18926
+        // If this wsdl was imported, the top-level wsdl should pass it's own schemaManager
+        // which we should reuse.
+        if (topLevelManager != null)
+        {
+            _schemaManager = topLevelManager;
+        }
+        _xml = xml;
+        _log = Log.getLogger("mx.rpc.wsdl.WSDL");
+        processNamespaces();
+        processSchemas();
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    private var resourceManager:IResourceManager =
+                                    ResourceManager.getInstance();
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    public function get schemaManager():SchemaManager
+    {
+        if (_schemaManager == null)
+        {
+            _schemaManager = new SchemaManager();
+            _schemaManager.schemaConstants = schemaConstants;
+        }
+
+        return _schemaManager;
+    }
+
+    public function get schemaConstants():SchemaConstants
+    {
+        if (_schemaConstants == null)
+            _schemaConstants = SchemaConstants.getConstants(xml);
+
+        return _schemaConstants;
+    }
+
+    public function get soapConstants():SOAPConstants
+    {
+        if (_soapConstants == null)
+            _soapConstants = SOAPConstants.getConstants(xml);
+        
+        return _soapConstants;
+    }
+
+    public function get targetNamespace():Namespace
+    {
+        return _targetNamespace;
+    }
+
+    public function get wsdlConstants():WSDLConstants
+    {
+        if (_wsdlConstants == null)
+            _wsdlConstants = WSDLConstants.getConstants(xml);
+
+        return _wsdlConstants;
+    }
+
+    /**
+     * The raw XML representing the WSDL starting from the top-level
+     * definitions element.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get xml():XML
+    {
+        return _xml;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /*
+        FIXME:
+        1. Validate that the targetNamespace matches the one defined on the
+           import XML
+        2. Also, check that the import being added does not cause a cyclic
+           relationship.
+    */
+    public function addImport(targetNamespace:Namespace, wsdl:WSDL):void
+    {
+        if (importsManager == null)
+            importsManager = new QualifiedResourceManager();
+
+        importsManager.addResource(targetNamespace, wsdl);
+    }
+
+    public function addSchema(schema:Schema):void
+    {
+        schemaManager.addSchema(schema);
+    }
+
+    public function getOperation(operationName:String, serviceName:String = null, portName:String = null):WSDLOperation
+    {
+        var port:WSDLPort = getPort(serviceName, portName);
+        var binding:WSDLBinding = port.binding;
+        var portType:WSDLPortType = binding.portType;
+        var operation:WSDLOperation = portType.getOperation(operationName);
+        return operation;
+    }
+
+    /**
+     * Locate a port for a service by name. If a serviceName is provided, a
+     * service is first located, otherwise the first service is used by default.
+     * Once a service has been selected, the search then considers the port.
+     * If a portName is not provided, the first port is used by default.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function getPort(serviceName:String = null, portName:String = null):WSDLPort
+    {
+        var port:WSDLPort;
+
+        var service:WSDLService = getService(serviceName, portName);
+        if (service != null)
+        {
+            if (portName == null)
+                port = service.defaultPort;
+            else
+                port = service.getPort(portName);
+        }
+
+        if (port == null)
+        {
+            var message:String = resourceManager.getString(
+                "rpc", "noServiceAndPort", [ serviceName, portName ]);
+            throw new Fault("Client.NoSuchPort", message);
+        }
+
+        return port;
+    }
+
+    /**
+     * Search for WSDL service and port by name. If a serviceName is not
+     * provided the first service found will be selected by default. 
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function getService(serviceName:String = null, portName:String = null):WSDLService
+    {
+        var service:WSDLService;
+        var port:WSDLPort;
+
+        if (serviceMap != null && serviceName != null)
+        {    
+            service = serviceMap[serviceName];
+            if (service != null)
+            {
+                if (portName != null)
+                    port = service.getPort(portName);
+
+                if (port == null)
+                {
+                    var tempService:WSDLService = parseService(serviceName, portName);
+                    for each (var p:WSDLPort in tempService.ports)
+                    {
+                        service.addPort(p);
+                    }
+                }
+            }
+        }
+
+        // We didn't find a service, so we parse to find one...
+        if (service == null)
+        {
+            service = parseService(serviceName, portName);
+
+            var message:String;
+            var detail:String;
+
+            if (service != null)
+            {
+                if (serviceMap == null)
+                    serviceMap = {};
+
+                serviceMap[service.name] = service;
+            }
+            else if (serviceName != null)
+            {
+                message = resourceManager.getString(
+                    "rpc", "noSuchServiceInWSDL", [ serviceName ]);
+                throw new Fault("Client.NoSuchService", message);
+            }
+            else
+            {
+                message = resourceManager.getString(
+                    "rpc", "noServiceElement");
+                detail = resourceManager.getString(
+                    "rpc", "noServiceElement.details", [ "" ]);
+                throw new Fault("Server.NoServicesInWSDL", message, detail);
+            }
+        }
+
+        return service;
+    }
+
+    public function getTypes(targetNamespace:Namespace):XML
+    {
+        var types:XML;
+
+        // First, check current WSDL for types element
+        var typesXMLList:XMLList = xml.elements(wsdlConstants.typesQName);
+        if (typesXMLList.length() > 0)
+        {
+            // There should only be one types element.
+            types = typesXMLList[0];
+        }
+        else if (importsManager != null)
+        {
+            // Check WSDL imports for types element
+            var imports:Array = importsManager.getResourcesForNamespace(targetNamespace);
+            for each (var childWSDL:WSDL in imports)
+            {
+                types = childWSDL.getTypes(targetNamespace);
+                if (types != null)
+                    break;
+            }
+        }
+
+        return types;
+    }
+
+    /**
+     * Search for a requested service in the definitions XML, including all
+     * WSDL imports. This is the usual entry point to start parsing the WSDL as
+     * only one service and one of its port will be used at any time.
+     * <p>
+     * If the service name is not specified, the first service is used by
+     * default. If a service is located it is parsed and then the search
+     * continues for the requested port, which is in turn parsed, and so forth.
+     * </p>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parseService(serviceName:String = null, portName:String = null):WSDLService
+    {
+        var service:WSDLService;
+        var serviceXML:XML;
+
+        // First, look for the service in this WSDL
+        var serviceXMLList:XMLList = xml.elements(wsdlConstants.serviceQName);
+        for each (var x:XML in serviceXMLList)
+        {
+            if (serviceName == null)
+            {
+                // Select the first service if a service name wasn't specified
+                serviceXML = x;
+                serviceName = x.@name.toString();
+                break;
+            }
+            else if (x.@name == serviceName)
+            {
+                serviceXML = x;
+                break;
+            }
+        }
+
+        if (serviceXML != null)
+        {
+            // We have the service, now look for the port
+            service = new WSDLService(serviceName);
+
+            var port:WSDLPort = parsePort(service, serviceXML, portName);
+
+            if (port != null)
+            {
+                service.addPort(port);
+            }
+        }
+        else if (importsManager != null)
+        {
+            // Otherwise, look for the service in our WSDL imports (assuming
+            // the port must be in the same import as the service).
+            var imports:Array = importsManager.getResources();
+            for each (var childWSDL:WSDL in imports)
+            {
+                service = childWSDL.parseService(serviceName, portName);
+                if (service != null)
+                    break;
+            }
+        }
+
+        return service;
+    }
+
+    /**
+     * Search for a requested port in the given service XML. If a port
+     * name was not specified, the first port is used by default.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parsePort(service:WSDLService, serviceXML:XML, portName:String = null):WSDLPort
+    {
+        var port:WSDLPort;
+        var portXML:XML;
+
+        var portXMLList:XMLList = serviceXML.elements(wsdlConstants.portQName);
+        for each (var x:XML in portXMLList)
+        {
+            if (portName == null)
+            {
+                portXML = x;
+                portName = x.@name.toString();
+                break;
+            }
+            else if (x.@name == portName)
+            {
+                portXML = x;
+                break;
+            }
+        }
+
+        if (portXML != null)
+        {
+            // We have the port, now look for the location and binding
+            port = new WSDLPort(portName, service);
+
+            var soapAddressXMLList:XMLList;
+            soapAddressXMLList = portXML.elements(wsdlConstants.soapAddressQName);
+            if (soapAddressXMLList.length() > 0)
+            {
+                port.endpointURI = soapAddressXMLList[0].@location.toString();
+            }
+
+            var prefixedBindingName:String = portXML.@binding.toString();
+            var bindingQName:QName = schemaManager.getQNameForPrefixedName(prefixedBindingName, portXML);
+
+            var binding:WSDLBinding = parseBinding(bindingQName);
+
+            if (binding != null)
+            {
+                port.binding = binding;
+            }
+            else
+            {
+                var message:String = resourceManager.getString(
+                    "rpc", "unrecognizedBindingName",
+                    [ bindingQName.localName, bindingQName.uri ]);
+                throw new Fault("WSDL.UnrecognizedBindingName", message);
+            }
+        }
+
+        return port;
+    }
+
+    /**
+     * Search for a binding by QName. If a URI is not specified, the
+     * targetNamespace is assumed. FIXME: We may need to consider whether
+     * formElementDefault is set to qualified or not.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parseBinding(bindingQName:QName):WSDLBinding
+    {
+        var binding:WSDLBinding;
+        var bindingXML:XML;
+
+        // First, look for the binding in this WSDL
+        var bindingXMLList:XMLList = xml.elements(wsdlConstants.bindingQName);
+        for each (var x:XML in bindingXMLList)
+        {
+            if (x.@name == bindingQName.localName)
+            {
+                bindingXML = x;
+                break;
+            }
+        }
+
+        if (bindingXML != null)
+        {
+            // We have the binding, now look for the style, transport,
+            // operation and portType information
+            binding = new WSDLBinding(bindingQName.localName);
+
+            // Look for the SOAP specific binding that controls the basic
+            // structure of requests made to and from a WSDL operation, and
+            // specifies the default style for operations. It does not make any
+            // claims as to the encoding or format of the message.
+            //
+            //     <soap:binding transport="uri"? style="rpc|document"?>
+            //
+            var soapBindingXMLList:XMLList;
+            soapBindingXMLList = bindingXML.elements(wsdlConstants.soapBindingQName);
+            if (soapBindingXMLList.length() > 0)
+            {
+                var style:String = soapBindingXMLList[0].@style.toString();
+                binding.style = style;
+
+                var transport:String = soapBindingXMLList[0].@transport.toString();
+                binding.transport = transport;
+            }
+
+            // The port type name must match the type specified on the binding.
+            //
+            //    <wsdl:binding name="nmtoken" type="qname">*
+            //
+            var prefixedTypeName:String = bindingXML.@type.toString();
+            var portTypeQName:QName = schemaManager.getQNameForPrefixedName(prefixedTypeName, bindingXML);
+            var portType:WSDLPortType = new WSDLPortType(portTypeQName.localName);
+            binding.portType = portType;
+
+            // We parse binding information for each operation and its
+            // input, output and fault messages before processing the port type
+            // so that we can establish encoding rules and whether subsets of
+            // the parts have been declared for the Body.
+            //
+            //    <wsdl:operation name="nmtoken">*
+            //
+            var operationXMLList:XMLList = bindingXML.elements(wsdlConstants.operationQName);
+            for each (var operationXML:XML in operationXMLList)
+            {
+                var operationName:String = operationXML.@name.toString();
+                var operation:WSDLOperation = new WSDLOperation(operationName);
+                operation.schemaManager = schemaManager;
+                operation.namespaces = namespaces;
+                operation.wsdlConstants = wsdlConstants;
+
+                // Look for soapAction as we expect HTTP based SOAP binding
+                // and any operation-specific style information.
+                //
+                //    <soap:operation soapAction="uri"? style="rpc|document"?>?
+                //
+                var soapOperationXMLList:XMLList = operationXML.elements(wsdlConstants.soapOperationQName);
+                if (soapOperationXMLList.length() > 0)
+                {
+                    var soapAction:String = soapOperationXMLList[0].@soapAction.toString();
+                    operation.soapAction = soapAction;
+                    var opStyle:String = soapOperationXMLList[0].@style.toString();
+                    if (opStyle == "")
+                        operation.style = binding.style;
+                    else
+                        operation.style = opStyle;
+                }
+
+                // Record the encoding format each of the messages of this
+                // operation. The SOAP Body, Fault and Header sections are
+                // described.
+                // 
+                //     <soap:body parts="nmtokens"? use="literal|encoded"?
+                //         encodingStyle="uri-list"? namespace="uri"?>
+                //
+                //     <soap:header message="qname" part="nmtoken" use="literal|encoded"
+                //         encodingStyle="uri-list"? namespace="uri"?>*
+                //
+
+                var operationExtensionXMLList:XMLList;
+                var operationExtensionXML:XML;
+                var encoding:WSDLEncoding;
+                var extensionXMLList:XMLList;
+                var extensionXML:XML;
+                var extensionName:String;
+                var extensionMessage:WSDLMessage;
+
+                // WSDL Input Message
+                operationExtensionXMLList = operationXML.elements(wsdlConstants.inputQName);
+                if (operationExtensionXMLList.length() > 0)
+                {
+                    operationExtensionXML = operationExtensionXMLList[0];
+                    operation.inputMessage = new WSDLMessage();
+
+                    // SOAP Body
+                    extensionXMLList = operationExtensionXML.elements(wsdlConstants.soapBodyQName);
+                    if (extensionXMLList.length() > 0)
+                    {
+                        extensionXML = extensionXMLList[0];
+                        encoding = parseEncodingExtension(extensionXML);
+                        operation.inputMessage.encoding = encoding;
+                    }
+
+                    // SOAP Header
+                    extensionXMLList = operationExtensionXML.elements(wsdlConstants.soapHeaderQName);
+                    for each (extensionXML in extensionXMLList)
+                    {
+                        extensionMessage = parseHeader(operationName, extensionXML);
+                        operation.inputMessage.addHeader(extensionMessage);
+                    }
+
+                    // SOAP Header Fault
+                    extensionXMLList = operationExtensionXML.elements(wsdlConstants.soapHeaderFaultQName);
+                    for each (extensionXML in extensionXMLList)
+                    {
+                        extensionMessage = parseHeader(operationName, extensionXML);
+                        operation.inputMessage.addHeaderFault(extensionMessage);
+                    }
+                }
+
+                // WSDL Output Message
+                operationExtensionXMLList = operationXML.elements(wsdlConstants.outputQName);
+                if (operationExtensionXMLList.length() > 0)
+                {
+                    operationExtensionXML = operationExtensionXMLList[0];
+                    operation.outputMessage = new WSDLMessage();
+
+                    // SOAP Body
+                    extensionXMLList = operationExtensionXML.elements(wsdlConstants.soapBodyQName);
+                    if (extensionXMLList.length() > 0)
+                    {
+                        extensionXML = extensionXMLList[0];
+                        encoding = parseEncodingExtension(extensionXML);
+                        operation.outputMessage.encoding = encoding;
+                    }
+
+                    // SOAP Header
+                    extensionXMLList = operationExtensionXML.elements(wsdlConstants.soapHeaderQName);
+                    for each (extensionXML in extensionXMLList)
+                    {
+                        extensionMessage = parseHeader(operationName, extensionXML);
+                        operation.outputMessage.addHeader(extensionMessage);
+                    }
+
+                    // SOAP Header Fault
+                    extensionXMLList = operationExtensionXML.elements(wsdlConstants.soapHeaderFaultQName);
+                    for each (extensionXML in extensionXMLList)
+                    {
+                        extensionMessage = parseHeader(operationName, extensionXML);
+                        operation.outputMessage.addHeaderFault(extensionMessage);
+                    }
+                }
+
+                // WSDL Fault Message
+                //
+                //     <soap:fault name="nmtoken" use="literal|encoded"
+                //         encodingStyle="uri-list"? namespace="uri"?>
+                //
+                operationExtensionXMLList = operationXML.elements(wsdlConstants.faultQName);
+                for each (operationExtensionXML in operationExtensionXMLList)
+                {
+                    // SOAP Fault
+                    extensionXMLList = operationExtensionXML.elements(wsdlConstants.soapFaultQName);
+                    if (extensionXMLList.length() > 0)
+                    {
+                        extensionXML = extensionXMLList[0];
+                        var faultName:String = extensionXML.@["name"].toString();
+                        extensionMessage = new WSDLMessage(faultName);
+                        encoding = parseEncodingExtension(extensionXML, false, true);
+                        extensionMessage.encoding = encoding;
+                        operation.addFault(extensionMessage);
+                    }
+                }
+
+                portType.addOperation(operation);
+            }
+
+            // Now that we've read the SOAP binding information for each
+            // operation, we can find and parse the port type which is a
+            // named set of abstract operations and the abstract messages
+            // involved.
+            parsePortType(portTypeQName, portType);
+        }
+        else if (importsManager != null)
+        {
+            // FIXME: USE QNAME URI TO LOOK UP IMPORT BY NAMESPACE!
+            
+            // Otherwise, look for the binding in our WSDL imports.
+            var imports:Array = importsManager.getResources();
+            for each (var childWSDL:WSDL in imports)
+            {
+                binding = childWSDL.parseBinding(bindingQName);
+                if (binding != null)
+                    break;
+            }
+        }
+
+        return binding;
+    }
+
+    /**
+     * Search for a portType by QName. If a URI is not specified, the
+     * targetNamespace is assumed.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parsePortType(portTypeQName:QName, portType:WSDLPortType):Boolean
+    {
+        var portTypeXML:XML;
+        var foundMatchingPortType:Boolean;
+
+        // First, look for the portType in this WSDL
+        var portTypeXMLList:XMLList = xml.elements(wsdlConstants.portTypeQName);
+        for each (var x:XML in portTypeXMLList)
+        {
+            if (x.@name == portTypeQName.localName)
+            {
+                portTypeXML = x;
+                break;
+            }
+        }
+
+        if (portTypeXML != null)
+        {
+            foundMatchingPortType = true;
+
+            var operationsXMLList:XMLList = portTypeXML.elements(wsdlConstants.operationQName);
+            for each(var operationXML:XML in operationsXMLList)
+            {
+                // TODO: We may need to consider operation overloading!
+
+                // The binding operation nmtoken is unique and must match an
+                // operation defined in the associated portType. We've
+                // previously parsed the binding, so this operation must be
+                // located by name.
+                var operationName:String = operationXML.@name.toString();
+                var operation:WSDLOperation = portType.getOperation(operationName);
+
+                // If we don't have the binding information for this operation,
+                // skip it.
+                if (operation == null)
+                {
+                    _log.warn("An operation '{0}' was found in the port type but is missing binding information.", operationName);
+                    continue;
+                }
+
+                var messageName:String;
+                var messageQName:QName;
+                var message:WSDLMessage;
+
+                // Input Message
+                //
+                //     <wsdl:input name="nmtoken"? message="qname"/>
+                //
+                var inputXMLList:XMLList = operationXML.elements(wsdlConstants.inputQName);
+                if (inputXMLList.length() > 0)
+                {
+                    // Reset the schema scope for each message
+                    schemaManager.reset();
+
+                    messageName = inputXMLList[0].@message.toString();
+                    messageQName = schemaManager.getQNameForPrefixedName(messageName, inputXMLList[0]);
+                    message = operation.inputMessage;
+                    message.name = messageQName.localName;
+                    parseMessage(message, messageQName, operationName, WSDLConstants.MODE_IN);
+                }
+
+                // Output Message
+                //
+                //    <wsdl:output name="nmtoken"? message="qname"/>
+                //
+                var outputXMLList:XMLList = operationXML.elements(wsdlConstants.outputQName);
+                if (outputXMLList.length() > 0)
+                {
+                    // Reset the schema scope for each message
+                    schemaManager.reset();
+
+                    messageName = outputXMLList[0].@message.toString();
+                    messageQName = schemaManager.getQNameForPrefixedName(messageName, outputXMLList[0]);
+                    message = operation.outputMessage;
+                    message.name = messageQName.localName;
+                    parseMessage(message, messageQName, operationName, WSDLConstants.MODE_OUT);
+                }
+
+                // Fault Messages
+                //
+                //    <wsdl:fault name="nmtoken" message="qname"/>*
+                //
+                var faultsXMLList:XMLList = operationXML.elements(wsdlConstants.faultQName);
+                for each (var faultXML:XML in faultsXMLList)
+                {
+                    // Reset the schema scope for each message
+                    schemaManager.reset();
+
+                    var faultName:String = faultXML.@name.toString();
+                    message = operation.getFault(faultName);
+                    if (message != null)
+                    {
+                        messageName = faultXML.@message.toString();
+                        messageQName = schemaManager.getQNameForPrefixedName(messageName, faultXML);
+                        parseMessage(message, messageQName, operationName, WSDLConstants.MODE_FAULT);
+                    }
+                }
+
+                if (operation.style == SOAPConstants.DOC_STYLE)
+                {
+                    parseDocumentOperation(operation);
+                }
+            }
+        }
+        else if (importsManager != null)
+        {
+            // Then look for the portType in the imports...
+            var imports:Array = importsManager.getResources();
+            for each (var childWSDL:WSDL in imports)
+            {
+                foundMatchingPortType = childWSDL.parsePortType(portTypeQName, portType);
+                if (foundMatchingPortType)
+                    break;
+            }
+        }
+
+        return foundMatchingPortType;
+    }
+
+    /**
+     * Search for a message by QName. If a URI is not specified, the
+     * targetNamespace is assumed.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parseMessage(message:WSDLMessage, messageQName:QName, operationName:String, mode:int):Boolean
+    {
+        var messageXML:XML;
+        var foundMatchingMessage:Boolean;
+        var encoding:WSDLEncoding = message.encoding;
+
+        // First, look for the message in this WSDL
+        var messageXMLList:XMLList = xml.elements(wsdlConstants.messageQName);
+        for each (var x:XML in messageXMLList)
+        {
+            if (x.@name == messageQName.localName)
+            {
+                messageXML = x;
+                break;
+            }
+        }
+
+        if (messageXML != null)
+        {
+            foundMatchingMessage = true;
+
+            // If the message is not named we default to the operation name
+            // plus a standard suffix for input or output mode:
+            if (message.name == null || message.name == "")
+            {
+                if (mode == WSDLConstants.MODE_IN)
+                {
+                    message.name = operationName + "Request";
+                }
+                else if (mode == WSDLConstants.MODE_OUT)
+                {
+                    message.name = operationName + "Response";
+                }
+                
+                // FIXME: Handle soap fault message name if one wasn't provided
+            }
+
+            // Parse the message types
+            var partXMLList:XMLList = messageXML.elements(wsdlConstants.partQName);
+            for each (var partXML:XML in partXMLList)
+            {
+                var partName:String = partXML.@name;
+
+                // We skip a part if the SOAP encoding extension defines a 
+                // subset of parts and this part nmtoken isn't in the list...
+                if (encoding != null && !encoding.hasPart(partName))
+                {
+                    continue;
+                }
+
+                var part:WSDLMessagePart = parseMessagePart(partXML);
+                message.addPart(part);
+            }
+        }
+        else if (importsManager != null)
+        {
+            // Then look for the message in the imports...
+            var imports:Array = importsManager.getResources();
+            for each (var childWSDL:WSDL in imports)
+            {
+                foundMatchingMessage = childWSDL.parseMessage(message, messageQName, operationName, mode);
+                if (foundMatchingMessage)
+                    break;
+            }
+        }
+
+        return foundMatchingMessage;
+    }
+
+    /**
+     * Returns a WSDL message part based on the name and looks for either an
+     * element QName or type QName to determine which definition describes
+     * this message part.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parseMessagePart(partXML:XML):WSDLMessagePart
+    {
+        var partName:String = partXML.@name;
+        var partQName:QName = new QName("", partName);
+        var part:WSDLMessagePart = new WSDLMessagePart(partQName);
+        var partXMLElement:String = partXML.@element;
+        var partXMLType:String = partXML.@type;
+
+        // Consider type or element
+        if (partXMLElement != "")
+        {
+            var elementName:String = partXML.@element;
+            var elementQName:QName = schemaManager.getQNameForPrefixedName(elementName, partXML);
+            part.element = elementQName;
+        }
+        else if (partXMLType != "")
+        {
+            var typeName:String = partXML.@type;
+            var typeQName:QName = schemaManager.getQNameForPrefixedName(typeName, partXML);
+            part.type = typeQName;
+        }
+
+        return part;
+    }
+
+    /**
+     * Looks for the SOAP encoding extensions based on the type of WSDL
+     * operation message. SOAP encoding is required for SOAP Body, Header
+     * (header and headerfault) and Fault extensions.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parseHeader(operationName:String, headerXML:XML):WSDLMessage
+    {
+        var headerName:String = headerXML.@["part"].toString();
+        var headerMessage:WSDLMessage = new WSDLMessage(headerName);
+        var encoding:WSDLEncoding = parseEncodingExtension(headerXML, true);
+        headerMessage.encoding = encoding;
+        parseMessage(headerMessage, encoding.message, operationName, WSDLConstants.MODE_HEADER);
+        return headerMessage;
+    }
+
+    /**
+     * Looks for the SOAP encoding extensions based on the type of WSDL
+     * operation message. SOAP encoding is required for SOAP Body, Header
+     * (header and headerfault) and Fault extensions.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parseEncodingExtension(extensionXML:XML, isHeader:Boolean = false, isFault:Boolean = false):WSDLEncoding
+    {
+        var encoding:WSDLEncoding = new WSDLEncoding();
+        encoding.useStyle = extensionXML.@["use"].toString();
+        encoding.namespaceURI = extensionXML.@["namespace"].toString();
+        encoding.encodingStyle = extensionXML.@["encodingStyle"].toString();
+
+        if (isHeader)
+        {
+            var messageName:String = extensionXML.@["message"].toString();
+            encoding.message = schemaManager.getQNameForPrefixedName(messageName, extensionXML);
+            encoding.setParts(extensionXML.@["part"].toString());
+        }
+        else if (!isFault)
+        {
+            encoding.setParts(extensionXML.@["parts"].toString());
+        }
+
+        return encoding;
+    }
+
+    /**
+     * A Document-Literal operation may make use of "wrapped" style. If so,
+     * then the message parts should be replaced by the the individual wrapped
+     * parts so that the SOAP encoders correctly bind ActionScript input params
+     * to message params, and SOAP decoders correctly bind output params
+     * to predictable ActionScript constructs. Essentially the wrappers should
+     * be an encoding detail that is invisible to the Flex developer.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parseDocumentOperation(operation:WSDLOperation):void
+    {
+        var part:WSDLMessagePart;
+        var element:XML;
+        var elementTypeString:String;
+        var elementType:QName;
+        var complexTypes:XMLList;
+        var complexType:XML;
+        var attributes:XMLList;
+        var sequences:XMLList;
+        var sequence:XML;
+
+        // Check whether this operation's input is literal and "wrapped".
+        if (operation.inputMessage != null
+            && operation.inputMessage.encoding != null
+            && operation.inputMessage.encoding.useStyle == SOAPConstants.USE_LITERAL)
+        {
+            // A "wrapped" input message must:
+            // 1. Have a single part.
+            // 2. The part is an element.
+            // 3. The element's name MUST be the same as the name of the operation.
+            // 4. The element's complex type must have no attributes and define
+            //    a sequence of zero or more elements (which serve as the input 
+            //    params).
+            var input:WSDLMessage = operation.inputMessage;
+            if (input.parts != null && input.parts.length == 1)
+            {
+                // Reset the schema scope for each wrapped part
+                schemaManager.reset();
+                
+                part = input.parts[0];
+                if (part.element != null)
+                {
+                    element = schemaManager.getNamedDefinition(part.element, schemaConstants.elementTypeQName);
+                    if (element != null && element.@["name"] == operation.name)
+                    {
+                        elementTypeString = element.@["type"];
+                        if (elementTypeString != null && elementTypeString != "")
+                        {
+                            elementType = schemaManager.getQNameForPrefixedName(elementTypeString, element);
+                            complexType = schemaManager.getNamedDefinition(elementType, schemaConstants.complexTypeQName);
+                        }
+                        else
+                        {
+                            complexTypes = element.elements(schemaConstants.complexTypeQName);
+                            if (complexTypes.length() == 1)
+                            {
+                                complexType = complexTypes[0];
+                            }
+                        }
+
+                        if (complexType != null)
+                        {                    
+                            attributes = complexType.elements(schemaConstants.attributeQName);
+                            if (attributes.length() == 0)
+                            {
+                                sequences = complexType.elements(schemaConstants.sequenceQName);
+
+                                // The sequence may be omitted entirely for
+                                // zero-param operation signatures
+                                if (complexType.elements().length() == 0 || sequences.length() == 1)
+                                {
+                                    input.isWrapped = true;
+                                    input.wrappedQName = part.element;
+                                    input.parts = [];
+
+                                    if (sequences.length() == 1)
+                                    {
+                                        // Use the wrapped parts to redefine the
+                                        // signature of the input message.
+                                        sequence = sequences[0];
+                                        var requestElements:XMLList = sequence.elements(schemaConstants.elementTypeQName);
+                                        for each (var requestElement:XML in requestElements)
+                                        {
+                                            // FIXME: Should we skip wrapped parts
+                                            // if the SOAP encoding extension defines
+                                            // a subset?
+                                            part = parseWrappedMessagePart(requestElement);
+                                            input.addPart(part);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }                        
+                }
+            }
+        }
+
+        // Reset wrapped element's type variables
+        complexType = null;
+        elementTypeString = null;
+
+        // Check whether this operation's output is literal and "wrapped".
+        if (operation.outputMessage != null
+            && operation.outputMessage.encoding != null
+            && operation.outputMessage.encoding.useStyle == SOAPConstants.USE_LITERAL)
+        {
+            // A "wrapped" output message must:
+            // 1. Have a single part.
+            // 2. The part is an element.
+            // 3. This element's complexType must have no attributes and define
+            //    a sequence of zero or more elements (which serve as the output
+            //    params).
+            var output:WSDLMessage = operation.outputMessage;
+            if (output.parts != null && output.parts.length == 1)
+            {
+                part = output.parts[0];
+                if (part.element != null)
+                {
+                    // Reset the schema scope for each wrapped part
+                    schemaManager.reset();
+
+                    element = schemaManager.getNamedDefinition(part.element, schemaConstants.elementTypeQName);
+                    if (element != null)
+                    { 
+                        elementTypeString = element.@["type"];
+                        if (elementTypeString != null && elementTypeString != "")
+                        {
+                            elementType = schemaManager.getQNameForPrefixedName(elementTypeString, element);
+                            complexType = schemaManager.getNamedDefinition(elementType, schemaConstants.complexTypeQName);
+                        }
+                        else
+                        {
+                            complexTypes = element.elements(schemaConstants.complexTypeQName);
+                            if (complexTypes.length() == 1)
+                            {
+                                complexType = complexTypes[0];
+                            }
+                        }
+
+                        if (complexType != null)
+                        {  
+                            attributes = complexType.elements(schemaConstants.attributeQName);
+                            if (attributes.length() == 0)
+                            {
+                                sequences = complexType.elements(schemaConstants.sequenceQName);
+
+                                // The sequence may be omitted entirely for
+                                // zero-param operation signatures
+                                if (complexType.elements().length() == 0 || sequences.length() == 1)
+                                {
+                                    output.isWrapped = true;
+                                    output.wrappedQName = part.element;
+                                    output.parts = [];
+
+                                    if (sequences.length() == 1)
+                                    {
+                                        // Use the wrapped parts to redefine the
+                                        // return type signature of the output
+                                        // message (multiple output parts will
+                                        // be returned as a map)
+                                        sequence = sequences[0];
+                                        var resultElements:XMLList = sequence.elements(schemaConstants.elementTypeQName);
+                                        for each (var resultElement:XML in resultElements)
+                                        {
+                                            // FIXME: Should we skip wrapped parts
+                                            // if the SOAP encoding extension defines
+                                            // a subset?
+                                            part = parseWrappedMessagePart(resultElement);
+                                            output.addPart(part);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns a WSDL message part based on the name and looks for either an
+     * element QName or type QName to determine which definition describes
+     * this message part.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function parseWrappedMessagePart(elementXML:XML):WSDLMessagePart
+    {
+        // <element ref="..."> may be used to point to a top-level element definition
+        var ref:QName;
+        if (elementXML.attribute("ref").length() == 1)
+        {
+            ref = schemaManager.getQNameForPrefixedName(elementXML.@ref, elementXML, true);
+            elementXML = schemaManager.getNamedDefinition(ref, schemaConstants.elementTypeQName);
+            if (elementXML == null)
+                throw new Error("Cannot resolve element definition for ref '" + ref + "'");
+        }
+
+        var partName:String = elementXML.@name;
+        var partQName:QName = schemaManager.getQNameForElement(partName, elementXML.@form);
+        var part:WSDLMessagePart = new WSDLMessagePart(partQName);
+
+        // However, since this is a local element that acts like a
+        // top-level element, we first check whether we need to
+        // special case the element definition.
+        var minOccurs:String = elementXML.@minOccurs;
+        var maxOccurs:String = elementXML.@maxOccurs;
+
+        // Furthermore, if minOccurs is set to 0, this part is optional
+        if (minOccurs != "" && parseInt(minOccurs) == 0)
+            part.optional = true;
+
+        if (ref != null)
+        {
+            // We have a reference to a top level element definition
+            part.element = ref;
+        }
+        else 
+        {
+            var partType:String = elementXML.@type;
+            if (partType != "" || !elementXML.hasComplexContent())
+            {
+                // We have a reference to a type definition
+                if (partType == null || partType == "")
+                    part.type = schemaConstants.anyTypeQName;
+                else 
+                    part.type = schemaManager.getQNameForPrefixedName(partType, elementXML);
+
+                if (minOccurs != "" || maxOccurs != "")
+                {
+                    part.definition = elementXML;
+                }
+            }
+            else if (elementXML.hasComplexContent())
+            {
+                // We have an inline type definition
+                part.definition = elementXML;
+            }
+        }
+
+        // If we found our element by reference, we now release the schema scope
+        if (ref != null)
+            schemaManager.releaseScope();
+
+        return part;
+    }
+
+    /**
+     * Determines the WSDL and SOAP versions from the definitions and creates
+     * a map of top level prefixes to namespaces.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function processNamespaces():void
+    {
+        if (_xml != null)
+        {
+            // Record the targetNamespace
+            var tns:String = _xml.@targetNamespace.toString();
+            _targetNamespace = new Namespace(tns);
+
+            // Initialize Namespaces
+            namespaces = {};
+            
+            // Determine WSDL and SOAP Version
+            var nsArray:Array = _xml.namespaceDeclarations();
+            for each (var ns:Namespace in nsArray)
+            {
+                namespaces[ns.prefix] = ns;
+            }
+
+            // Initialize WSDL Constants
+            _wsdlConstants = WSDLConstants.getConstants(_xml);
+            _schemaConstants = SchemaConstants.getConstants(_xml);
+
+            // Also record these top level namespaces with our SchemaManager
+            schemaManager.addNamespaces(namespaces);
+        }
+    }
+
+    private function processSchemas():void
+    {
+        var types:XML = getTypes(targetNamespace);
+        if (types != null)
+        {
+            var schemas:XMLList = types.elements(schemaConstants.schemaQName);
+            for each (var schemaXML:XML in schemas)
+            {
+                var schema:Schema = new Schema(schemaXML);
+                addSchema(schema);
+            }
+        }
+    }
+
+    /**
+     * Manages WSDL imports.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */ 
+    private var importsManager:QualifiedResourceManager;
+
+    /**
+     * Logs warnings encountered while parsing WSDL.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var _log:ILogger;
+
+    /**
+     * Maps a namespace prefix (as a <code>String</code>) to a
+     * <code>Namespace</code> (i.e. this helps to resolve a prefix to a URI).
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var namespaces:Object;
+
+    /**
+     * Provides a static cache of the constants for various versions of XSD.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var _schemaConstants:SchemaConstants;
+
+    /**
+     * A map of target namespaces to XSD Schemas that describe the types 
+     * used in this WSDL.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var _schemaManager:SchemaManager;
+
+    /**
+     * Map to cache a WSDLService by service name. The cache is cleared 
+     * when a new definitions element is set for the WSDL.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var serviceMap:Object;
+
+    private var _soapConstants:SOAPConstants;
+
+    /**
+     * WSDL target namespace.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var _targetNamespace:Namespace;
+
+    /**
+     * Provides a static cache of the constants for various versions of WSDL.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var _wsdlConstants:WSDLConstants;
+
+    /**
+     * The raw XML representing the WSDL definitions top level element.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var _xml:XML;
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/wsdl/WSDLBinding.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/wsdl/WSDLBinding.as
new file mode 100644
index 0000000..8497d46
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/wsdl/WSDLBinding.as
@@ -0,0 +1,171 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.wsdl
+{
+
+import mx.rpc.soap.SOAPConstants;
+
+/**
+ * A binding defines the message format and protocol for messages sent
+ * to and from operations as defined by a particular portType.
+ * <p>
+ * Currently only SOAP binding is supported for WSDL.
+ * </p>
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class WSDLBinding
+{
+   /**
+    * Creates a new WSDLBinding. Currently, only SOAP binding is
+    * supported for WSDL.
+    *
+    * @param name The unique name of this binding.
+    *  
+    *  @langversion 3.0
+    *  @playerversion Flash 9
+    *  @playerversion AIR 1.1
+    *  @productversion Flex 3
+    */
+    public function WSDLBinding(name:String)
+    {
+        super();
+        _name = name;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * The unique name of this binding.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */ 
+    public function get name():String
+    {
+        return _name;
+    }
+
+    /**
+     * The portType for this binding which provides the interface definitions
+     * for the operations of this binding.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get portType():WSDLPortType
+    {
+        return _portType;
+    }
+
+    public function set portType(value:WSDLPortType):void
+    {
+        _portType = value;
+    }
+
+    [Inspectable(enumeration="document,rpc", defaultValue="document", category="General")]
+    /**
+     * Represents a SOAP binding style attribute which is the default for any
+     * operation defined under this binding. The style indicates whether an
+     * operation is RPC-oriented (messages containing parameters and return
+     * values) or document-oriented (message containing document(s)).
+     * <p>
+     * The default is <code>document</code>.
+     * </p>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get style():String
+    {
+        if (_style == null)
+            _style = SOAPConstants.DEFAULT_OPERATION_STYLE;
+
+        return _style;
+    }
+
+    public function set style(value:String):void
+    {
+        _style = value;
+    }
+
+    [Inspectable(defaultValue="http://schemas.xmlsoap.org/soap/http/", category="General")]
+    /**
+     * Represents a SOAP binding transport attribute which indicates the
+     * URI of the transport used to send SOAP encoded messages. 
+     * The default URI is http://schemas.xmlsoap.org/soap/http/ which signifies
+     * SOAP over HTTP (and is currently the only transport supported).
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get transport():String
+    {
+        if (_transport == null)
+            _transport = WSDLConstants.SOAP_HTTP_URI;
+
+        return _transport;
+    }
+
+    public function set transport(value:String):void
+    {
+        _transport = value;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    /**
+     * @private
+     */
+    public function toString():String
+    {
+        return "WSDLBinding name=" + _name
+            + ", style=" + _style
+            + ", transport=" + _transport;
+    }
+
+    private var _name:String;
+    private var _portType:WSDLPortType;
+    private var _style:String;
+    private var _transport:String;
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/wsdl/WSDLConstants.as b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/wsdl/WSDLConstants.as
new file mode 100644
index 0000000..7f2da3c
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/wsdl/WSDLConstants.as
@@ -0,0 +1,257 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.rpc.wsdl
+{
+
+import mx.utils.StringUtil;
+import mx.utils.URLUtil;
+
+[ExcludeClass]
+
+/**
+ * Manages the constants for a particular version of WSDL (and its
+ * accompanying version of SOAP).
+ * 
+ * The default version is WSDL 1.1.
+ * 
+ * @private
+ */
+public class WSDLConstants
+{
+    public function WSDLConstants(wsdlNS:Namespace = null, soapNS:Namespace = null)
+    {
+        super();
+
+        // Default to WSDl 1.1 and SOAP 1.1
+        if (wsdlNS == null)
+            wsdlNS = new Namespace(WSDL_PREFIX, WSDL_URI);
+        if (soapNS == null)
+            soapNS = new Namespace(WSDL_SOAP_PREFIX, WSDL_SOAP_URI);
+
+        _wsdlNS = wsdlNS;
+        _soapNS = soapNS;
+
+        definitionsQName = new QName(wsdlURI, "definitions");
+        importQName = new QName(wsdlURI, "import");
+        typesQName = new QName(wsdlURI, "types");
+        messageQName = new QName(wsdlURI, "message");
+        portTypeQName = new QName(wsdlURI, "portType");
+        bindingQName = new QName(wsdlURI, "binding");
+        serviceQName = new QName(wsdlURI, "service");
+        documentationQName = new QName(wsdlURI, "documentation");
+        portQName = new QName(wsdlURI, "port");
+        operationQName = new QName(wsdlURI, "operation");
+        inputQName = new QName(wsdlURI, "input");
+        outputQName = new QName(wsdlURI, "output");
+        partQName = new QName(wsdlURI, "part");
+        faultQName = new QName(wsdlURI, "fault");   
+        wsdlArrayTypeQName = new QName(wsdlURI, "arrayType"); 
+
+        soapAddressQName = new QName(soapURI, "address");
+        soapBindingQName = new QName(soapURI, "binding");
+        soapOperationQName = new QName(soapURI, "operation");
+        soapBodyQName = new QName(soapURI, "body");
+        soapFaultQName = new QName(soapURI, "fault");
+        soapHeaderQName = new QName(soapURI, "header");
+        soapHeaderFaultQName = new QName(soapURI, "headerfault");
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    // 
+    //--------------------------------------------------------------------------
+
+    public function get soapURI():String
+    {
+        return soapNamespace.uri;
+    }
+
+    public function get wsdlURI():String
+    {
+        return wsdlNamespace.uri;
+    }
+
+    public function get soapNamespace():Namespace
+    {
+        return _soapNS;
+    }
+
+    public function get wsdlNamespace():Namespace
+    {
+        return _wsdlNS;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods
+    // 
+    //--------------------------------------------------------------------------
+
+    public static function getConstants(xml:XML):WSDLConstants
+    {
+        var wsdlNS:Namespace;
+        var soapNS:Namespace;
+
+        if (xml != null)
+        {
+            var nsArray:Array = xml.inScopeNamespaces();
+            for each (var ns:Namespace in nsArray)
+            {
+                if (URLUtil.urisEqual(ns.uri, WSDL_URI))
+                {
+                    wsdlNS = ns;
+                }
+                else if (URLUtil.urisEqual(ns.uri, WSDL20_URI))
+                {
+                    wsdlNS = ns;
+                }
+                if (URLUtil.urisEqual(ns.uri, WSDL_SOAP_URI))
+                {
+                    soapNS = ns;
+                }
+                else if (URLUtil.urisEqual(ns.uri, WSDL20_SOAP_URI))
+                {
+                    soapNS = ns;
+                }
+                else if (URLUtil.urisEqual(ns.uri, WSDL20_SOAP12_URI))
+                {
+                    soapNS = ns;
+                }
+            }
+        }
+
+        // Default to WSDL 1.1
+        if (wsdlNS == null)
+            wsdlNS = new Namespace(WSDL_PREFIX, WSDL_URI);
+
+        if (soapNS == null)
+            soapNS = new Namespace(WSDL_SOAP_PREFIX, WSDL_SOAP_URI);
+
+        if (constantsCache == null)
+            constantsCache = {};
+
+        var constants:WSDLConstants = constantsCache[wsdlNS.uri];
+        if (constants == null)
+        {
+            constants = new WSDLConstants(wsdlNS, soapNS);
+            constantsCache[wsdlNS.uri] = constants;
+        }
+
+        return constants;
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    // Variables
+    // 
+    //--------------------------------------------------------------------------
+
+    // WSDL QNames
+    public var definitionsQName:QName;
+    public var typesQName:QName;
+    public var messageQName:QName;
+    public var portTypeQName:QName;
+    public var bindingQName:QName;
+    public var serviceQName:QName;
+    public var importQName:QName;
+    public var documentationQName:QName;
+    public var portQName:QName;
+    public var operationQName:QName;
+    public var inputQName:QName;
+    public var outputQName:QName;
+    public var partQName:QName;
+    public var faultQName:QName;
+    public var wsdlArrayTypeQName:QName;
+
+    // WSDL SOAP QNames
+    public var soapAddressQName:QName;
+    public var soapBindingQName:QName;
+    public var soapOperationQName:QName;
+    public var soapBodyQName:QName;
+    public var soapFaultQName:QName;
+    public var soapHeaderQName:QName;
+    public var soapHeaderFaultQName:QName;
+
+    /**
+     * The namespace representing the version of SOAP used by a WSDL,
+     * currently 1.1 is supported.
+     * FIXME: Need SOAP 1.2 support.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var _soapNS:Namespace;
+
+    /**
... 12758 lines suppressed ...