Nice Katy! Overloading the SoapClient object is a very elegant workaround. I'm assuming that every call to SoapClient->[specific web method] eventually goes through __doRequest()? For example, the invocation: $client = new DotNetSoapClient($wsdl); $client->MyMethod($param1, $param2); will eventually trigger the overloaded __doRequest() method? Neat, you can manipulate the request any way you want. I don't think I'd recommend removing the xsi:type attributes, as they may be needed by the server, but you certainly could replace them with the "correct" type definition ("SOAP-ENC:Array"). The implementation would be a bit fragile, as it would rely in PHP always using the string "SOAP-ENC" as the local name for the soap encoding namespace, but that's probably something upon which we can rely. -Peter "Katy Coe" <info@intelligentstreaming.com> wrote in message 5.2.1.1.2.20060121010629.00bc5d48@mail.intelligentstreaming.com">news:5.2.1.1.2.20060121010629.00bc5d48@mail.intelligentstreaming.com... > Hi everyone, > > I'm using PHP 5.1.x as a client and .NET 1.1 as a server; I also am writing > both the client and server end of my application. While running basic tests > I noticed this problem too, just with arrays of simple types like int and > string, .NET's deserialiser will complain "No type associated with Xml key > <yournamespace> ArrayOfString" or some such. > > As has already been discussed in the thread, I traced the problem to the > xsi:type attribute generated by PHP on the element in the SOAP request that > wraps all the array items. I don't know if this is a PHP bug or a .NET/Java > bug as I'm not a SOAP guru, but the very simple workaround I made goes as > follows: > > class DotNetSoapClient extends SoapClient > { > public function __construct($wsdl, $options = array()) { > parent::__construct($wsdl, $options); > } > > public function __doRequest($request, $location, $action, $version) > { > $dom = DOMDocument::loadXML($request); > $xpath = new DOMXPath($dom); > > // Array serialisation: remove the xsi:type attribute from all > arrays encoded using SOAP-ENC:arrayType > // as this causes an "no type associated with Xml key"-type SOAP > server error in .NET > $nodes = > $xpath->query('/SOAP-ENV:Envelope/SOAP-ENV:Body/*//*[@SOAP-ENC:arrayType > and @xsi:type]'); > > foreach ($nodes as $node) > $node->removeAttribute('type'); > > $request = $dom->saveXML(); > return parent::__doRequest($request, $location, $action, > $version); > } > } > > This workaround: > > 1. Requires no underlying knowledge of SOAP protocol to use (does not > require you to form your own SOAP request) > 2. Works with .NET and I assume works or is easily adapted for Java > 3. Only generates one request/response roundtrip over the network > 4. Can be used if you don't have access to the server > > Since most web services in the real world use Java or .NET, I think that - > even if this is a bug in their implementations and not PHP's - that it > might be wise to at least include a flag in future versions of ext/soap > that would allow the client developer to control how the request is > serialised ("interop mode" or some such). From my naive perspective, that > would seem to be a good compromise. > > Hope the workaround helps someone anyway :-) > > Katy. > > At 08:18 PM 01/20/2006, Peter Guy wrote: > >Dmitry, > > > >Thank you for your attention to this thread. > > > >I have indeed applied a workaround to the server: added a pre-filter to the > >servlet that finds and changes PHP's array typing to something the server > >understands. Check out message 2083 (http://news.php.net/php.soap/2083) for > >more details. > > > >Thank you for considering a change in this area of PHP's SOAP > >implementation. Overall, I am impressed with PHP's SOAP implementation. > > From the PHP developer's point of view, it's simple, elegant, and easy to > >use. Just feed it a WSDL and you're off and running. This array type > >definition issue has been the only implementation problem with which I've > >had to deal. > > > >-Peter > > > >""Dmitry Stogov"" <dmitry@zend.com> wrote in message > >000101c61d99$b5686f80$6e02a8c0@thinkpad">news:000101c61d99$b5686f80$6e02a8c0@thinkpad... > >Hi Peter, > > > >Right now ext/soap hasn't workaround for this problem. > >I'll look and may be will create it later. > > > >Note that some other SOAP implementations have the same interopability > >issue. > >Look into google. > > > >http://www.google.com/search?hl=en&rls=GGLD%2CGGLD%3A2005-13%2CGGLD%3Aen&q= % > >2B%22No+Deserializer+found+to+deserialize+a%22+%2Barray&lr= > > > >May be you will find a way to fix the server itself. > > > >Thanks. Dmitry. > > > > > -----Original Message----- > > > From: Peter Guy [mailto:pguy@vrcis.com] > > > Sent: Wednesday, January 18, 2006 10:45 PM > > > To: soap@lists.php.net > > > Subject: Re: Re: Java/Oracle server, PHP 5.1.2 client, > > > array of complexTypes, Deserializer error > > > > > > > > > Thanks for the clarification, Dmitry. > > > > > > I see that it is legal to type a SOAP array the way that PHP > > > does it, but I don't think it's the right way to do it. :-) > > > > > > The problem is, how will the SOAP server with which I'm > > > dealing have any knowledge of the "type derived there from"? > > > Unless it's written in PHP, it doesn't necessarily parse > > > requests against the schema in the WSDL, so it likely won't > > > have any knowledge of that derived type. > > > > > > So, is there any way to cajole PHP into defining arrays with > > > a "SOAP-ENC:Array" type rather than the "type derived there > > > from"? Perhaps formatting the WSDL differently, like using > > > elements rather than complex types? > > > > > > Any suggestions? > > > > > > -Peter > > > > > > ""Dmitry Stogov"" <dmitry@zend.com> wrote in message > > > 000001c61c06$4bfd97d0$6e02a8c0@thinkpad">news:000001c61c06$4bfd97d0$6e02a8c0@thinkpad... > > > > H Peter, > > > > > > > > This is well known issue, but not a php/soap bug. > > > > The problem that some SOAP implementations don't confirm to SOAP > > > > specification and don't accept types derived from array. > > > > > > > > See: http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383522 > > > > > > > > "SOAP arrays are defined as having a type of "SOAP-ENC:Array" or A > > > > TYPE DERIVED THERE FROM." > > > > > > > > Thanks. Dmitry. > > > > > > > > > -----Original Message----- > > > > > From: Peter Guy [mailto:pguy@vrcis.com] > > > > > Sent: Wednesday, January 18, 2006 3:52 AM > > > > > To: soap@lists.php.net > > > > > Subject: Re: Java/Oracle server, PHP 5.1.2 client, > > > array of > > > > > complexTypes, Deserializer error > > > > > > > > > > > > > > > Since this is such a long post, I'll put all of my > > > comments up here, > > > > > rather than throughout the post or at the bottom. > > > > > > > > > > Thanks for taking the time to generate more stubs, and > > > confirming my > > > > > suspicions that this is a PHP bug, Michael. > > > > > > > > > > However, you state that, "The error is that php names the > > > individual > > > > > structs/complex types item...", but I'm pretty sure the > > > error is in > > > > > the xsi:type attribute of the BARS element. PHP fills > > > the xsi:type > > > > > attribute with "<my > > > > > namespace>:ArrayOfBar", when it should be "<SOAP-ENC :Array". > > > > > Every other client I've seen specifies the type of an > > > array element > > > > > as "<SOAP-ENC namespace>:Array", so I'm almost sure that > > > this is a > > > > > PHP bug. > > > > > > > > > > Where do I go from here? Shall I submit a PHP bug report? > > > > > > > > > > -Peter > > > > > > > > > > "Michael Rasmussen" <mir@miras.org> wrote in message > > > > > pan.2006.01.18.00.19.56.504455@miras.org">news:pan.2006.01.18.00.19.56.504455@miras.org... > > > > > > On Tue, 17 Jan 2006 11:04:21 -0800, Peter Guy wrote: > > > > > > > > > > > > > So, my questions: > > > > > > > > > > > > > > 1. Is the WSDL formatted the right way for PHP? Could it be > > > > > > > formatted differently, so as to coerce PHP into supplying the > > > > > > > correct "type" for > > > > > the > > > > > > > BARS element? > > > > > > Well, it seems to be correct wsdl. mono(C#) and > > > > > gsoap(c/c++) has now > > > > > > problems in creating a correct proxy: The mono proxy: > > > > > > > > > > > // > > > > > -------------------------------------------------------------- > > > > > ----------- > > > > > ----- > > > > > > // <autogenerated> > > > > > > // This code was generated by a tool. > > > > > > // Mono Runtime Version: 1.1.4322.2032 > > > > > > // > > > > > > // Changes to this file may cause incorrect behavior > > > > > and will be lost > > > > > if > > > > > > // the code is regenerated. > > > > > > // </autogenerated> > > > > > > > > > > > // > > > > > -------------------------------------------------------------- > > > > > ----------- > > > > > ----- > > > > > > > > > > > > // > > > > > > // This source code was auto-generated by Mono Web Services > > > > > > Description > > > > > Language Utility > > > > > > // > > > > > > > > > > > > /// <remarks/> > > > > > > > > > [System.Web.Services.WebServiceBinding(Name="CustomerServicePort", > > > > > Namespace="http://CustomerService.wsdl")] > > > > > > [System.Diagnostics.DebuggerStepThroughAttribute()] > > > > > > [System.ComponentModel.DesignerCategoryAttribute("code")] > > > > > > [System.Xml.Serialization.SoapInclude(typeof(Bar))] > > > > > > public class CustomerService : > > > > > System.Web.Services.Protocols.SoapHttpClientProtocol { > > > > > > > > > > > > public CustomerService() { > > > > > > this.Url = > > > > > "http://vrcweb1.vrcis.com/custserv/CustomerService"; > > > > > > } > > > > > > > > > > > > [System.Web.Services.Protocols.SoapRpcMethodAttribute("", > > > > > RequestNamespace="CustomerService", > > > > > ResponseNamespace="CustomerService")] > > > > > > [return: System.Xml.Serialization.SoapElement("return")] > > > > > > public Bar[] EchoBars(Bar[] BARS) { > > > > > > object[] results = this.Invoke("EchoBars", new > > > object[] { > > > > > > BARS}); > > > > > > return ((Bar[])(results[0])); > > > > > > } > > > > > > > > > > > > public System.IAsyncResult BeginEchoBars(Bar[] BARS, > > > > > System.AsyncCallback callback, object asyncState) { > > > > > > return this.BeginInvoke("EchoBars", new object[] { > > > > > > BARS}, callback, asyncState); > > > > > > } > > > > > > > > > > > > public Bar[] EndEchoBars(System.IAsyncResult asyncResult) { > > > > > > object[] results = this.EndInvoke(asyncResult); > > > > > > return ((Bar[])(results[0])); > > > > > > } > > > > > > } > > > > > > > > > > > > /// <remarks/> > > > > > > > > > > > [System.Xml.Serialization.SoapType(Namespace="http://www.vrcis > > > > > .com/CustomerS > > > > > erviceAPIV1")] > > > > > > public class Bar { > > > > > > > > > > > > /// <remarks/> > > > > > > public string NAME; > > > > > > } > > > > > > > > > > > > The gsoap proxy: > > > > > > /** @mainpage CustomerService Definitions > > > > > > > > > > > > @section CustomerServiceBinding Service Binding > > > > > > "CustomerServiceBinding" > > > > > > > > > > > > @subsection CustomerServiceBinding_operations Operations > > > > > > > > > > > > - @ref ns1__EchoBars > > > > > > > > > > > > @subsection CustomerServiceBinding_ports Endpoint Ports > > > > > > > > > > > > - http://vrcweb1.vrcis.com/custserv/CustomerService > > > > > > > > > > > > */ > > > > > > > > > > > > // Note: modify this file to customize the generated data type > > > > > declarations > > > > > > > > > > > > //gsoapopt w > > > > > > #import "stl.h" > > > > > > /// Built-in attribute "SOAP-ENC:arrayType" > > > > > > typedef char *SOAP_ENC__arrayType; > > > > > > > > > > > > /* > > > > > > To customize the names of the namespace prefixes generated > > > > > by wsdl2h, > > > > > modify > > > > > > the prefix names below and add the modified lines to > > > typemap.dat > > > > > > to run > > > > > wsdl2h: > > > > > > > > > > > > ns2 = http://www.vrcis.com/CustomerServiceAPIV1 > > > > > > */ > > > > > > > > > > > > //gsoap ns2 schema namespace: > > > > > http://www.vrcis.com/CustomerServiceAPIV1 > > > > > > //gsoap ns2 schema form: unqualified > > > > > > > > > > > > // Forward declarations > > > > > > class ArrayOfBar; > > > > > > class ns2__Bar; > > > > > > > > > > > > // End of forward declarations > > > > > > > > > > > > > > > > > > /// Schema http://www.vrcis.com/CustomerServiceAPIV1 > > > > > complexType "Bar" > > > > > > > > > > > > class ns2__Bar > > > > > > { public: > > > > > > /// Element NAME of type xs:string > > > > > > std::string NAME > > > > > ; > > > > > ///< Required element > > > > > > /// A handle to the soap struct context that manages this > > > > > class instance > > > > > > struct soap *soap > > > > > ; > > > > > > }; > > > > > > > > > > > > /// Schema http://www.vrcis.com/CustomerServiceAPIV1 complexType > > > > > "ArrayOfBar" > > > > > > > > > > > > /// SOAP encoded array of > > > > > > "http://www.vrcis.com/CustomerServiceAPIV1":Bar > > > > > > class ArrayOfBar > > > > > > { public: > > > > > > /// Pointer to an array of ns2__Bar* > > > > > > ns2__Bar* *__ptr > > > > > ; > > > > > > /// Size of the dynamic array > > > > > > int __size > > > > > ; > > > > > > /// A handle to the soap struct context that manages this > > > > > class instance > > > > > > struct soap *soap > > > > > ; > > > > > > }; > > > > > > > > > > > > //gsoap ns1 service name: CustomerServiceBinding > > > > > > //gsoap ns1 service type: CustomerServicePortType //gsoap ns1 > > > > > > service port: > > > > > http://vrcweb1.vrcis.com/custserv/CustomerService > > > > > > //gsoap ns1 service namespace: CustomerService > > > > > > > > > > > > /// Operation response struct "ns1__EchoBarsResponse" > > > of service > > > > > > binding > > > > > "CustomerServiceBinding" operation "ns1__EchoBars" > > > > > > struct ns1__EchoBarsResponse > > > > > > { > > > > > > ArrayOfBar* return_; > > > > > > }; > > > > > > > > > > > > /// Operation "ns1__EchoBars" of service binding > > > > > > "CustomerServiceBinding" > > > > > > > > > > > > /** > > > > > > > > > > > > Operation details: > > > > > > > > > > > > - SOAP RPC > > > > > encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" > > > > > > > > > > > > C stub function (defined in soapClient.c[pp]): > > > > > > @code > > > > > > int soap_call_ns1__EchoBars(struct soap *soap, > > > > > > NULL, // char *endpoint = NULL selects default endpoint for > > > > > > this > > > > > operation > > > > > > NULL, // char *action = NULL selects default action for > > > > > this operation > > > > > > ArrayOfBar* BARS, > > > > > > struct ns1__EchoBarsResponse& > > > > > > ); > > > > > > @endcode > > > > > > > > > > > > C++ proxy class (defined in soapCustomerServiceBindingProxy.h): > > > > > > class CustomerServiceBinding; > > > > > > > > > > > > */ > > > > > > > > > > > > //gsoap ns1 service method-style: EchoBars rpc > > > > > > //gsoap ns1 service method-encoding: EchoBars > > > > > http://schemas.xmlsoap.org/soap/encoding/ > > > > > > //gsoap ns1 service method-action: EchoBars "" > > > > > > int ns1__EchoBars( > > > > > > ArrayOfBar* BARS, > > > > > > struct ns1__EchoBarsResponse& ); > > > > > > > > > > > > /* End of CustomerService Definitions */ > > > > > > > > > > > > Parsing output from php: > > > > > > Supported functions: > > > > > > ArrayOfBar EchoBars(ArrayOfBar $BARS) > > > > > > Supported types: > > > > > > Bar ArrayOfBar[] > > > > > > struct Bar { > > > > > > string NAME; > > > > > > } > > > > > > Produced with this code: > > > > > > $client = new SoapClient( > > > > > > 'http://vrcweb1.vrcis.com/custserv/CustomerService?WSDL', > > > > > > $options > > > > > > ); > > > > > > if ($functions = $client->__getFunctions()) > > > > > > { > > > > > > echo "Supported functions:\n"; > > > > > > foreach ($functions as $function) > > > > > > echo $function, "\n"; > > > > > > } > > > > > > if ($types = $client->__getTypes()) > > > > > > { > > > > > > echo "Supported types:\n"; > > > > > > foreach ($types as $type) > > > > > > echo $type, "\n"; > > > > > > } > > > > > > > > > > > > The reason that it is not working in php is a bug in the proxy > > > > > > that php is creating! > > > > > > > > > > > > The request sent: > > > > > > <BARS SOAP-ENC:arrayType="ns2:Bar[1]" > > > xsi:type="ns2:ArrayOfBar"> > > > > > > <item xsi:type="ns2:Bar"> > > > > > > <NAME xsi:type="xsd:string">bar none</NAME> > > > > > > </item> > > > > > > </BARS> > > > > > > > > > > > > This is how it should be - which your http-client > > > > > demonstrates: <BARS > > > > > > SOAP-ENC:arrayType="ns1:Bar[1]" xsi:type="SOAP-ENC:Array"> > > > > > > <Bar xsi:type="ns1:Bar"> > > > > > > <NAME xsi:type="xsd:string">String Value</NAME> > > > > > > </Bar> > > > > > > </BARS> > > > > > > > > > > > > The error is that php names the individual structs/complex > > > > > types item > > > > > > but they must be named Bar. The error is therefore on the > > > > > client side > > > > > > (php) which does not send a correct formated request. I am > > > > > possitively > > > > > > convinced that receiving will work as can be seen under > > > supported > > > > > > types above. You could try sending a raw xml request to your > > > > > > server but let php handle the response to have this observation > > > > > > confirmed. > > > > > > > > > > > > -- > > > > > > Hilsen/Regards > > > > > > Michael Rasmussen > > > > > > > > > > > > > > http://keyserver.veridis.com:11371/pks/lookup?op=get&search=0xE3E809 > > > > > 17 -- PHP Soap Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php