Voici la version G o o g l e de la page mise en cache de http://www.djkaty.com/drupal/php-wsdl extraite le 12 avr 2008 22:31:30 GMT.
La version « En cache » proposée par G o o g l e correspond à la page telle qu’elle se présentait lors de la dernière consultation effectuée par Google.
Il se peut que la page ait été modifiée depuis cette date. Cliquez ici pour consulter la page actuelle (sans mises en valeur).
Cette page mise en cache peut renvoyer à des images qui ne sont plus disponibles. Cliquez ici pour obtenir uniquement le texte mis en cache.
Pour créer un lien avec cette page ou l'inclure dans vos favoris/signets, utilisez l'adresse suivante : http://www.google.com/search?q=cache:wrMzcWcQHcMJ:www.djkaty.com/drupal/php-wsdl+wsdl-writer+site:djkaty.com&hl=fr&ct=clnk&cd=1&gl=fr&client=firefox-a.


Google n'est ni affilié aux auteurs de cette page ni responsable de son contenu.
Les termes de recherche suivants ont été mis en valeur : wsdl writer 

Automatic WSDL Generation in PHP 5 | Katy's Homepage

Automatic WSDL Generation in PHP 5

Downloads for the software described here are available on the downloads page. If site is down, you can directly download wsdl-writer-0.3-katy.1.tar.gz on placeoweb.com.

About WSDL

WSDL (Web Services Description Language) is part of the XML Web Services technology platform. WSDL files describe to web service clients what services are available at a particular endpoint (server), and how the request and response messages should be (de)serialised. Find out more by reading the Web Services Description Language (WSDL) 1.1 W3C Note.

Typically, WSDL files are automatically generated from web service code using reflection, and are imported into clients at design-time. Visual Studio, for example, uses WSDL files to create proxy classes allowing the developer to call remote web services as simple method calls on a local object, making the process seamless (as if you were just calling a local method).

The two main platforms used for web services in the real world - J2EE and .NET - can both generate WSDL files easily from code because they are strongly typed languages. This is important because XML web services typically pass strongly typed data between client and server.

WSDL generation in PHP

PHP is a weakly typed language (meaning it is not necessary to declare a variable's content type when the variable itself is defined, and casts between eg. numbers and strings happen automatically depending on the context in which a variable is used), therefore reflection to generate WSDL files is impossible. This is a serious limitation for the applicability of PHP as a web services platform as it prevents PHP web services from having easy interoperability with clients written in other languages.

There have been several attempts to write WSDL auto-generation code for PHP. They typically work by having the developer provide additional data about the types of each argument and return value to each web service defined, for example in comments or arrays.

All of the published solutions are rather limited. Perhaps the best attempt I found is David Giffin's wsdl-writer-0.3, available at www.giffin.org. It operates by parsing comments immediately before a web service method to determine the types of its arguments. Here is a simple example:

class SimpleService {
    /**
     * Add method
     *
     * @param int $a First integer
     * @param int $b Second integer
     * @return int Result of addition
     */
    public function Add($a, $b)
    {
        return $a + $b;
    }
}


Some notes on syntax:

  • The comment parsing is very strict. You must not leave any empty lines between the closing */ and the method declaration.
  • Object properties must be declared using the exact syntax /** @var int Some integer value */ on the line immediately preceding the property declaration.
  • The types specified after @param and @return must be valid XSD types or complexTypes you have created yourself.

wsdl-writer does a very good job of generating WSDL for simple requests but has some major limitations as it stands. David unfortunately does not maintain wsdl-writer so I have decided to publish my modifications here.

WSDL Writer 0.3-katy.1

The following issues are addressed in this release:

Interoperability improvements:

  • PHP web services can now be imported into Visual Studio via their WSDL files (schema namespace fix)
  • When creating array types, the wsdl:arrayType attribute will now correctly use the xsd namespace for arrays of primitive types and tns (the target namespace) for arrays of complexTypes (previously tns was used for everything, which causes interoperability failures with .NET and Java)
  • Object complexType definitions with array properties will now be correctly serialised as eg. type="tns:ArrayOfstring" instead of type="tns:string[]" (this problem caused interoperability failures with .NET and Java)

Feature additions:

  • Binary attachments of type xsd:base64Binary are now supported
    • Specify "@param base64Binary $file" or "@return base64Binary" (case-sensitive) to trigger automatic encoding and decoding of binary arguments (such as images) at the client and server.
  • SOAP header support added
    • This is a significant enhancement which enables PHP web services to process eg. authentication or payment credentials supplied in headers, without having to modify every method of your web services to deal with authentication or other metadata that should preferably be supplied in headers.
    • To create a SOAP header processor in a PHP SOAP server, define methods in your web service class with the same names as the header elements you wish to process. The header methods will be called in document order followed by the body method, using a single instance of the class (the same instance will persist over each method call).
    • For automatic WSDL generation, specify that a method processes a SOAP header by including @internal soapheader before the method definition. To specify that a particular web service method requires certain SOAP headers, include @internal soaprequires FirstHeader SecondHeader .... (space-delimited list of header method names).
    • You can also create derived classes to facilitate encapsulation of SOAP header processing. This is desirable to avoid code repitition when you have several web service methods which use the same set of headers. To implement this, define a base class which processes your headers, and derive from it to create a web service class with your web service methods.
    • Limitations: The WSDL specification says that <soap:header> binding elements don't have to use the same <message> as those used by the <operation> being bound. My implementation only allows the same to be used. This should have no effect on your services in practice.
    • Limitations: .NET generates SOAP headers whose element names are the type names of their arguments. This means each header must include (and optionally return) precisely one argument; additionally the argument must be a complexType for the web service to import properly into Visual Studio. This also means that the PHP 5 method name which processes the header must be the same as the type name of its argument, eg. public function LoginObject($loginobject) where $loginobject is of type LoginObject. PHP 5 doesn't have the element naming, argument count or complexType restrictions, but in order to produce interoperable WSDL and eliminate the possibility of duplicate <part> names in a single <message> (where the arguments to a header and body method have the same name), my implementation co-erces part names representing headers to be the name of the type used as the argument, not the name of the argument itself. Therefore, if you use my implementation to generate WSDL, you must follow the .NET limitations, even if your client is PHP. Again, in practice, this should only be a minor inconvenience.
    • Access from .NET: In .NET languages such as C# and VB.NET, SOAP headers are available as read/write properties of the web service proxy class generated when your WSDL is imported into Visual Studio.
  • Objects and arrays are recursively scanned to an arbitrary depth for further objects and arrays, to correctly find and serialise all the types required to create a SOAP request into the <types> section of the WSDL file. This effectively means you can now pass and return types of arbitrary complexity among your web services - a very powerful enhancement.
    • Background: The original release of wsdl-writer-0.3 only scans the top level of types used (ie. the arguments and return parameters of each method). If any such argument or return parameter has properties which are themselves complexTypes or arrays of complexTypes (such as objects which have other objects or arrays of objects as public member variables), these are also needed in the <types> section to fully define the parent type.
    • Example: If you have a web service with returns an array of Foo, and Foo has properties of class types Bar and Baz, and Bar has a property of type array of string, the following types will be defined in the WSDL file: ArrayOfFoo, Foo, Bar, Baz and ArrayOfstring (the original release code would only include Foo and its type definition would be empty).

    Other bug fixes:

    • Command-line WSDL generation now works correctly
    • Multiple complexType class definitions in the same file which have some properties with the same name could cause the <types> section of the WSDL file to be generated incorrectly. This has been fixed.
    • Constructors and PHP magic methods will be excluded from the generated WSDL
      • SOAP servers using SOAP sessions may have a constructor in their web service classes to initialise new sessions to default values, so this exclusion is important
    • Strict Standards warnings in PHP 5 fixed

    Processing SOAP headers in a PHP SOAP server

    Here is an example of a web service class which processes headers and a body method:

     
    // To be supplied as a SOAP header element - remember that individual headers must
    // consist of exactly one complexType argument, so basic xsd types must be boxed in a class
    class WrappedString
    {
        /** @var string Data */
        public $data;
        
        public function __construct($s)
        {
            $this->data = $s;
        }
    }
    
    // Login credentials to be supplied as a SOAP header
    class LoginObject
    {
        /** @var int Login */
        public $login;
        /** @var int Password */
        public $password;
        
        public function __construct($l, $p)
        {
            $this->login = $l;
            $this->password = $p;
        }
    }
    
    // Arbitrary object returned by the test web service method
    // to prove that the header data was stored in the same class instance
    class TestObject
    {
        /** @var string Result string */
        public $result;
        /** @var int Demo session key */
        public $sessionkey;
        
        public function __construct($r, $k)
        {
            $this->result = $r;
            $this->sessionkey = $k;
        }
    }
    
    class MethodWithHeaders
    {
        public $sessionKey;
    
        /**
         * HeaderA SOAP header
         *
         * To process a SOAP header, create a function with the same name
    as the header's complexType.
         * Returned values will be sent back to the client as a SOAP response header.
         * This example returns the string in a response header, converted to uppercase.
         *
         * @param WrappedString $string Input string
         * @return WrappedString Capitalised string
         * @internal soapheader
         */
        public function WrappedString($string)
        {
            return new WrappedString(strtoupper($string->data));
        }
        
        /**
         * HeaderB SOAP header
         *
         * You don't have to return a value - you can store the details sent
         * in the header for later use.
         *
         * @param LoginObject $loginobject Username and password
         * @internal soapheader
         */
        public function LoginObject($loginobject)
        {
            $this->sessionKey = $loginobject->login * $loginobject->password;
        }
        
        /**
         * Some test web service
         *
         * Body function - shows that a single MethodWithHeaders object
         * instantiation is used for all the headers and the body method,
         * because $this->sessionKey hasn't been declared static.
         *
         * @param string $string Input string
         * @return TestObject Input string and demo session key based on
    header fields
         * @internal soaprequires WrappedString LoginObject
         */
        public function testfunction($string)
        {
            return new TestObject($string, $this->sessionKey);
        }
    }


    NOTE: Ironically the type hinting introduced into PHP 5.1 causes PHP SOAP servers to fail, so you should not use type hinting in your web service method or header prototypes.

    Supplying SOAP headers and accessing SOAP response headers in a PHP web service client

    The following code calls the server example above. Some items in [square brackets] require substitution as appropriate.

    // Create SOAP client using only WSDL
    $headersClient = new SoapClient("[Location of WSDL file]"); 
    
    // Create headers (use same element name and type name
    // for .NET interoperability - not required for PHP)
    $headerA = new SoapHeader('[Namespace URI of WrappedString]',
                     'WrappedString', new WrappedString('some test string')); 
    $headerB = new SoapHeader('[Namespace URI of LoginObject]',
                     'LoginObject', new LoginObject(14, 3)); 
    $headersClient->__setSoapHeaders(array($headerA, $headerB)); 
    
    // Standard call which passes input headers
    // but doesn't offer access to output headers
    $headersClient->testfunction("Echo me!")); 
    
    // Call which allows access to output headers
    // (input headers persist until changed)
    $headersClient->__soapCall('testfunction', array("Echo me again!"),
                               null, null, $outputHeaders); 
    print_r($outputHeaders);


    Note you need to include definitions of WrappedString or LoginObject in the client code.

    Final notes

    The changes to wsdl-writer and examples above have been tested against PHP 5.1.1 and Visual Studio .NET 2003 (.NET Framework 1.1). For general usage examples please refer to the examples supplied with the source code.

    I hope you find this code useful!

    Please send feedback to katy (at) intelligentstreaming_dot_com.

  • wsdl question

    Hi Katy,

    you wrote excellent article, I can understand all, but can't somehow replicate.

    Here is what I was trying to do with recently installed PHP5 on my machine:
    $my_client = new SoapClient("http://www.webservicex.net/WeatherForecast.asmx?WSDL");

    $ans = $my_client->GetWeatherByZipCode( array('ZipCode' => '10011'));

    foreach ($ans as $k=>$v) {
    echo (string) $k . ' = ' ;
    echo (string) $v . "\n";
    }

    ?>
    And I got following error:
    GetWeatherByZipCodeResult =
    Catchable fatal error: Object of class stdClass could not be converted to string in /usr/home/myhome/test.php on line 12

    I was trying to do similar task with our own WSDL file and got the same error.

    Please, any advise? Thanks.

    Re: wsdl question

    You can't iterate over each key/value pair returned by the call and output them as strings because the return data is a WeatherForecasts object which itself contains and array of WeatherData objects among other things.

    Replace your foreach with var_export($ans); to see everything returned. If you want the returned object types to be the actual WDSL-defined types instead of stdClass, use a fudge like this (fully working example):

    <?php
    $my_client = new SoapClient("http://www.webservicex.net/WeatherForecast.asmx?WSDL",
          array('classmap' => array('WeatherForecasts' => 'WeatherForecasts',
                                    'WeatherData' => 'WeatherData')));
    
    foreach ($my_client->__getTypes() as $type)
    {
        $type = str_replace('struct ', 'class ', $type);
        $type = preg_replace('/^ (.*) (.*);/m', 'public $\2;', $type);
        eval($type);
    }
    	
    $ans = $my_client->GetWeatherByZipCode( array('ZipCode' => '10011'));
    
    var_export($ans);
    ?>

    Hope that helps!

    Katy.

    thanks

    Katy,

    thanks, it works and now I am better to understand how it works.

    I might ask you another question later on if I will get some other troubles.

    Any way, I am glad to find your site (google works) and will keep it in my bookmarks.

    extra line, wsdltype.php and primitive "float" type

    Hi Katy

    I am just getting my head around generating a wsdl from my code and I am getting the wsdl generator to work for me by editing example.php to my setup and running it from the command line. It outputs to stdout which I pipe to a wsdl file. The resulting wsdl definition file always ends up with an empty line at the top which I have to delete or it will not work. ...

    The wsdl generator was also choking when parsing "float" return values in my commented class. From what I understand "float" is a XSD primitive value. Adding "float" as a static primitive type inside ./classes/wsdltype.php allowed the script to work...

    Thanks for your efforts.

    Headers

    Hi Katy
    Thanks for the WSDL Gen . It's a very convenient tool
    After some sucessful web services implementations I've tried your header source code example but i'm facing a problem
    It looks as if the LoginObject function is not called at all

    Typically a
    echo var_export($headersClient->testfunction("Echo me!"),true);
    gives
    stdClass::__set_state(array( 'result' => 'Echo me!', 'sessionkey' => NULL, ))

    and outputheaders are an empty array

    I've ran my tests on both PHP5.1.1 and 5.2.4
    The source code is strictly like yours (i basically added the generated wsdl file and the soapserver instantiation)

    I just can't find what is wrong !

    Re: Headers

    The $outputHeaders array is only available when you use __soapCall to invoke the web method, not when you call it via its wrapper above. That's because the only way PHP gives you to specify where to put the output headers is via the output headers parameter in __soapCall.

    Hope that helps.

    I meant the outputheaders

    I meant the outputheaders were empty after the __soapCall

    But the problem seems to occur serverside in the process as i stated before.
    It looks as if soap headers are not being processed by PHP and the LoginObject function is not called

    Here is the soap request i receive on the server if it can help :

    [?xml version="1.0" encoding="UTF-8"?]
    [SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://myurl/myappdir/wsdl-writer/example/soap/myNameSpace" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="MethodWithHeaders" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"]
    [SOAP-ENV:Header]
    [ns2:WrappedString]
    [data]some test string[/data]
    [/ns2:WrappedString]
    [ns2:LoginObject]
    [login]14[/login]
    [password]3[/password]
    [/ns2:LoginObject]
    [/SOAP-ENV:Header]
    [SOAP-ENV:Body]
    [ns1:testfunction]
    [string xsi:type="xsd:string">Echo me again![/string]
    [/ns1:testfunction]
    [/SOAP-ENV:Body]
    [/SOAP-ENV:Envelope]

    Thanks again for your help. I really dont know what is wrong at that point :)

    Headers -- need help :)

    Hi Katy, first off Thank you for all the work you've put into this.

    I was wondering if you wouldn't mind to put up or send me a simple working example of how I can implement the headers for my web service.
    I've tried the example at the top and I dont seem to understand everything. I don't see how or where to set the passwords or how to authenticate a client accessing my web service and how to process the sessions. if you don't mind to give a simple demonstration it would be greatly appreciated (Im using VS2005 as a client).
    Again Thanks.

    Re: Headers - need help :)

    Hi Tino,

    The example above only shows how to use SOAP headers, there is no authentication code in it, or session code, you will have to write both yourself, you'll need a database of users and you'll need to decide whether to use PHP sessions or your own session scheme. The code for this will vary dramatically depending on what you want to do, and unfortunately I'm swamped right now so I don't really have time to sit and write a fully working standalone example, sorry.

    The general procedure would be to create a method where the client supplies as parameters a username and password (or other login credentials), the web service will validate this against a user database and, if the login is valid, create a session either in PHP or in database tables (or both), and return a session key to the client, which will then be used in SOAP headers for all subsequent method calls. You then write a header processing function which takes the session key and retrieves the user's session before the web service method being called is executed.

    Hope that helps, sorry for not providing code.

    Katy.

    ok no problem...

    thanks for putting me on the right path :)

    SoapHeaders and .NET

    Hi Katy,
    Thanks for your wonderful WSDL writer. It helped me get along with php and .NET and SOAP.
    Now I can't get soapheader to work in Visual Studio 2005. Your docs says it should be accessed as a read/write property, but it aint. It does not appear as a webservice method. I read in the comments that there is someone with the same problem, but then you just got out of hospital (are you doing OK at the moment?). Hope you can help me out. Thanks!

    Re: SoapHeaders and .NET

    I'm doing better now, thanks :-)

    If you use the exact service code in the article, and add a Web Reference in Visual Studio, you'll end up with a namespace called MethodWithHeaders. First create a reference to the web service:

    MethodWithHeaders.MethodWithHeadersService service = new MethodWithHeaders.MethodWithHeadersService();

    The class definitions for the headers (WrappedString and LoginObject) will be defined in the MethodWithHeaders namespace, so populate instances of them like this:

    MethodWithHeaders.WrappedString ws = new WrappedString();
    MethodWithHeaders.LoginObject lo = new LoginObject();
    
    ws.data = "Some string";
    
    lo.login = "Username";
    lo.password = "Password";

    Now populate the headers themselves with these objects:

    service.WrappedStringValue = ws;
    service.LoginObjectValue = lo;

    Note that .NET adds the text 'Value' to the SOAP header names when it defines them as properties.

    Now you're ready to call the service:

    MethodWithHeaders.TestObject result = service.testfunction("Another string");

    and you should be all done. Hope that helps!

    Misunderstood

    I guess I misunderstood the docs above..
    I thought that without defining a method with a soaprequires argument, the soapheader method also should appear to the client. But I now see it ain't. If I specify a method with the soaprequires argument, it is exposed and can be set. Although I cannot see the 'real' advantage you got when using headers, because stil you've to include them as a parameter in the client, where I thought a headervalue once set, always is sent along each request..

    Anywhow, it is sort of solved :)

    The SOAP headers are

    The SOAP headers are persisted in the client after they are first set.

    WSDL Writer in Windows how to?

    Hello!

    How can I use your WSDL writer in a WAMP (windows development) environment?

    The same way you use it in a

    The same way you use it in a LAMP or any other OS + web server + PHP environment. You'll have to be a bit more specific.

    Re: Re: Fix for type definition comment parsing limitation

    Personally i use the following line to parse docblock comments. It handles docblocks spread over multiple lines.

    DocBlockParser.php:
    if (preg_match("|/\*\*.*@var\s+([_a-zA-Z0-9\[\]]+)\s*([^(\*/)]*)\s*\*/|s", $commentLine, $matches)) {

    Additionally I changed line 25 and 29 to allow for underscores in classnames (of params/return types).

    "regex" => "|@param\s+([_a-zA-Z0-9\[\]]+)\s+\\\$([_a-zA-Z0-9]+)\s+(.*)|",

    "regex" => "|@return\s+([_a-zA-Z0-9\[\]]+)\s+(.*)|",

    WSDL Writer is a great tool!

    Working With .NET

    Was able to get the header authentication working in PHP, but in .NET, the header(ie, loginobject) authentication is being ignored. Does anyone have a working example using .Net as the client using the Soap header example from above?

    Re: Working With .NET

    Argh, yes, I can help you with this as I use .NET as the client to code with the kind of header authentication shown above, but, not right now as I just got out of hospital and unable to actually get to my main computer to find the code :/

    How to use the tool

    I have the tool downloaded but how can we use it to generate the WSDL file

    How do you generate the WSDL file?

    I just found the tool and cannot seem to get the WSDL file generated. I am using Windows XP.

    What are the procedures for the example that comes with the download and the one on the page? please let me know.

    Thanks.

    Document/Literal wrapped WSDL generator for PHP5?

    I need to generate a WSDL in Document/Literal wrapped style for our web service. Do you know of any tool that can do that? Is it possible to somehow use your encoder for it? /T

    Re: doc/lit

    Hi tz,

    I don't know of any tool to do that and I'm afraid the WSDL writer here only handles rpc/encoded (that is because that's how the original author David Giffin wrote it, I just added some enhancements and bug fixes). I would certainly be interested in implementing doc/lit as I think it would be a useful feature for alot of people, and something PHP is lacking, if you can point me to some spec or examples I will take a look sometime. If someone pays me I will do it immediately :P

    I'm aware the spec is on the W3C site but it's not very clearly presented IMHO so some examples would be handy.

    SCA

    After some investigation I found this in PHP:
    http://se.php.net/manual/en/ref.SCA.php

    It is automatically compliant with Doc/Lit Wrapped. If you have time, have a look at it. I'll be building a Web Service using SCA to try it out in the next few weeks.

    Fix for type definition comment parsing limitation

    Hi Katy, I decided to publish in the comments how fix the data type definition limitation of the original wsdl generator.
    Originally, the wsdl generator only recognize an class property if the comment format use one line: /**@var string Some comment*/, but with the next fix, the wsdl generator ignore the spaces in the comment line and other text. This is the fix:
    In the line 55 of the file DocBlockParser.php, change the regex expression "|/\*\*\s+@var\s+([a-zA-Z0-9\[\]]+)([^(\*/)]*)\*/|" with "|@var\s+([a-zA-Z0-9\[\]]+)|". This fix remove the datatype definition limitation.

    Re: Fix for type definition comment parsing limitation

    No worries, I was away when you emailed me the fix, I will release a patched version with a couple other bug fixes "soon" :-)

    Thanks for sending it in!

    How I create a complexType?

    Hi Katy,
    I try to map an objecto to complex type definition, but its don't work.
    This function return an object of type ComputationResult
    /**
    * @param string $leftSide The left side of an equation
    * @param string $operation The operation to perform
    * @param string $rightSide The right side of the equation
    * @return ComputationResult The Evaluate Result
    * @soapservice
    */
    public function compute($leftSide, $operation, $rightSide)
    {
    $result = new ComputationResult();
    $result->equation = "$leftSide $operation $rightSide";
    $result->result = $this->evaluateExpression($leftSide, $operation, $rightSide);
    if (count($this->errors)) {
    $result->success = false;
    $result->errors = $this->errors;
    }
    else {
    $result->success = true;
    }

    return $result;
    }

    This class define the complex datatype:
    class ComputationResult
    {
    /**
    * @var string The initial equation
    */
    public $equation;

    /**
    * @var string The computed result
    */
    public $result;

    /**
    * @var boolean Whether the computation succeeded
    */
    public $success;

    /**
    * @var array any errors that occured in the processing.
    */
    public $errors;
    }

    The WSDL complexType section that I hope is:







    But wsdl-writer generates:


    Help me please, thanks!!

    Re: How I create a complexType?

    Hi Fabio,

    The type definition comments have to be on one line due to a limitation in David's original comment parsing code. Re-write the class like this:

    class ComputationResult
    {
    /** @var string The initial equation */
    public $equation;
    
    /** @var string The computed result */
    public $result;
    
    /** @var boolean Whether the computation succeeded */
    public $success;
    
    /** @var array any errors that occured in the processing. */
    public $errors;
    }
    

    and it should work fine. Also, you don't need the @soapservice marker in the method comments. That marker doesn't exist anywhere, all public functions will be treated as web service methods automatically (private functions will be omitted from the WSDL).

    Hope that helps!

    Katy.

    Thanks Katy, Now its works

    Hi Katy,
    Thanks for your help, now its works :D.

    "array"

    Oh, and I forgot to mention, you can't use array as a type, XSD is strongly-typed so you need to specify what kind of array it is. If your errors are strings, use for example:

    /** @var string[] any errors that occurred in the processing */

    Hope that helps!

    Opps, the tag filter

    The WSDL complexType section that I hope is:
    <xsd:complexType name="ComputationResult">
    <xsd:all>
    <xsd:element name="equation" type="xsd:string"/>
    <xsd:element name="result" type="xsd:string"/>

    <xsd:element name="success" type="xsd:boolean"/>
    <xsd:element name="errors" type="soap-enc:Array"/>
    </xsd:all>
    </xsd:complexType>

    But wsdl-writer generates:

    <complexType name="ComputationResult">
    <sequence/>
    </complexType>

    Array Type - how do I specify them on the PHP comments?

    Hi Katy:

    Thank you very much for your article and enhancements to David's WSDL writer.
    I'm trying to write a web service in PHP 5 to be consumed by a Flash application.

    I'm using your WSDL Writer to generate my WSDL file. I have no problems when my methods return integers, strings or booleans.
    I even managed to make them return complexTypes which are previously defined as a class.

    For instance: I defined this class so it is used as a complexType:
    class GameID{
    /** @var int BoardID */
    var $board_id;
    /** @var int Turn */
    var $turn;
    function GameID($b,$t){
    $this->board_id = $b;
    $this->turn = $t;
    }
    }

    Then one of the methods in the Game Class (which is the actual service) returns a GameID. And that works fine:

    /**
    *
    * @param string $size BoardSize ( s,m,l )
    * @param int $playersnum Number of Players in Board
    * @return GameID ( BoardID and Turn )
    */
    function createGame($size,$playersnum){ ... }

    But... My question is: what if I wanted to return a list of -say- GameID objects?
    I know it would make no sense in this "createGame" function, but let's pretend I need to return a list of GameID objects.

    I tried the following: I created another class named "ListOfGameID":

    class ListOfGameID{
    /** @var Array */
    var $items;
    function ListOfGameID(){
    $this->items = Array();
    }
    /**
    * @param GameID $gid Game ID
    */
    function push($gid){
    array_push($this->items,$gid);
    }
    }

    Then I modified the "createGame" function so it returns an intance of that class:

    /**
    *
    * @param string $size BoardSize
    * @param int $playersnum Number of Players
    * @return ListOfGameID BoardID and Turn
    */
    function createGame($size,$playersnum){

    The WSDL Writer generated the WSDL with no errors.
    But now I'm trying to test the service using SoapIU, and I get an error when loading the WSDL file:
    "Thu Aug 30 18:29:04 ART 2007:ERROR:An error occured [http://localhost:81/banzai/SenTeServer/SenTe.wsdl:0:
    error: src-resolve.a: Could not find type 'Array@http://www.w3.org/2001/XMLSchema'.
    Do you mean to refer to the element named Array@http://schemas.xmlsoap.org/soap/encoding/
    (in soapEncoding.xsd)?], see error log for details"

    Let me know if this is not the right place to post this questions. Feel free to remove it from the comments if you want to.

    Thanks!
    JulianG

    Re: Array Type - how do I specify them on the PHP comments?

    Hi Julian!

    Yes, thank you for reminding me about something that has been on my todo list since Christmas - writing a proper tutorial for this code :-)

    Making the service return an array (be it of primitive types like int or of objects) is really easy, just add [] after the type in the comments:

    @return GameID[] Some game information

    No need to worry about creating intermediate objects or anything like that; when the WSDL writer comes across a type like GameID[] in the comments, it will generate WSDL first for GameID itself and then for ArrayofGameID, and will set the return (or input if its a @param) type for the SOAP messages to ArrayofGameID. All of that is transparent to you though, when you call the service, you will simply get a regular PHP array of GameID back just like you would expect :-)

    One of the issues with the original code was that if you used an array of objects as an input or return type, it would create the Arrayof... type in the WSDL but not the definition of the object itself; that was one of the things fixed in this release, if I remember correctly.

    Hope that helps!

    Katy.

    Array Type

    Oh! It was THAT easy?
    I tried it now and -of course- it worked like charm.
    Thank you very much, Katy!

    Cheers,
    JulianG

    WSDL Writer and Visual Studio 2005/.Net 2.0

    I tried adding the WSDL files generated by wsdl-writer (for the example and for one of my own simple test classes) in Visual Studio (2005) and found that VS is unable to generate class definitions from them.

    Re: WSDL Writer and Visual Studio 2005/.Net 2.0

    We can't see your screen so you'll have to be a bit more specific. What steps do you go through and what error message do you get?

    KatyThank you for the

    Katy

    Thank you for the feedback, I tried what you suggested but PHP does not appear to recognise the ArrayOfString type.

    See below - with comments on what is returned.

    Many Thanks

    Bill

    <html>
        <head>
            <title>Example</title>
        </head>
        <body>
    
            <?php 
    echo "Getting SOAP Function.<br>";
    $wsdl_url =  'http://www.ndlr.co.uk/paflookup/service1.wsdl';
    $paf     = new SoapClient($wsdl_url); 
    
    
    $version  = $paf->GetPAFVersion();
    echo $version->GetPAFVersionResult, "<br>";
    
    $params   = array(
        'strPcd' => "CR2 9NL",
        'strHouseno' => '43'
    );
    
    $address = $paf->FindAddress($params);
    $result=$address->FindAddressResult;
    
    // This returns the Text Array
    foreach ($result as $item)
        echo $item . "<br>";
    
    
    // ** This Returns Catchable fatal error: Object of class stdClass could not
    be converted to string in test2.php on line 30
    foreach ($address as $item)
        echo $item . "<br>";
    
    ?>
    
        </body>
    </html>
    

    Re: Katy Thank you for the

    You can use var_export() to see what is going on in your variables. Changing the web service call to:

    $address = $paf->FindAddress($params);
    var_export($address);

    gives:

    stdClass::__set_state(array(
       'FindAddressResult' =>
      stdClass::__set_state(array(
         'string' =>
        array (
          0 => '0',
          1 => NULL,
          2 => 'Object reference not set to an instance of an object.; 
    Raised at: getSubsmanMessages',
          3 => NULL,
          4 => NULL,
          5 => NULL,
    ...


    and so on down to index 254.

    You have to supply each parameter exactly one time; PHP has no respect for minOccurs or maxOccurs in WSDL files. Changing the parameters to:

    $params   = array(
        'strPcd' => "CR2 9NL",
        'strHouseno' => '43',
        'strcompare' => ''
    );

    gives:

    stdClass::__set_state(array(
       'FindAddressResult' =>
      stdClass::__set_state(array(
         'string' =>
        array (
          0 => '1',
          1 => NULL,
          2 => NULL,
          3 => 'FOUND',
          4 => NULL,
          5 => '43 Montague Avenue',
          6 => NULL,
          7 => NULL,
          8 => 'SOUTH CROYDON',
          9 => 'Surrey',
          10 => 'CR2 9NL',
          11 => NULL,
          12 => NULL,
    ...

    which is I assume the result you want. The reason there is a nested object with one property 'string' is because the WSDL you generated is in document/literal format with these definitions:

    <s:element name="FindAddressResponse">
      <s:complexType>
        <s:sequence>
          <s:element minOccurs="0" maxOccurs="1" name="FindAddressResult"
    type="s0:ArrayOfString" /> 
        </s:sequence>
      </s:complexType>
    </s:element>
    
    <s:complexType name="ArrayOfString">
      <s:sequence>
        <s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true"
    type="s:string" /> 
      </s:sequence>
    </s:complexType>
    

    If you want more PHP-friendly behaviour, change the WSDL to use rpc/encoded format (there is an attribute you can add to your ASP.NET WebMethods for that - check MSDN documentation), then the response payload and ArrayOfString will be defined somewhat like this:

      <message name="FindAddressResponse">
        <part name="return" type="tns:ArrayOfString"/>
      </message>
    ...
          <complexType name="ArrayOfString">
            <complexContent>
              <restriction base="soapenc:Array">
                <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
              </restriction>
            </complexContent>
          </complexType>
    

    (transplanting just those sections into your existing WSDL won't work, the whole schema has to be changed)

    With your existing schema, you can get the data out of the service like this:

    $address = $paf->FindAddress($params);
    $result = $address->FindAddressResult->string;
    
    foreach ($result as $item)
        echo $item . "<br>";
    

    I hope that helps! For additional consultancy please contact me for a support contract.

    ArrayOfString

    Katy

    Not sure if you can help. We have written some Web Services in .NET / IIS. The one in question returns an ArrayOfString (http://www.ndlr.co.uk/paflookup/service1.asmx/FindAddress ). One of our partners wants to access this from a Linux Web Site using PHP.

    How do we handle / access ArrayOfString objects from the PHP Code - Sorry very new to PHP so finding it hard to help them out.

    Any advice much appreciated.

    Thanks

    Bill

    Re: ArrayOfString

    <?php
    
    $service = new SoapClient("http://www.ndlr.co.uk/paflookup/service1.asmx?WSDL");
    
    $result = $service->FindAddress($strPcd, $strHouseno, $strcompare);
    
    foreach ($result as $item)
        echo $item . "\r\n";
    ?>

    Array addressing syntax for numerically indexed arrays in PHP is the same as for C# and you can find the documentation here: http://no.php.net/manual/en/language.types.array.php.

    Hope that helps.

    Dynamic Assisgnment of the Header

    Thanks for the great tutorial on SOAP headers! I have one question though, does anyone know how to modify a SOAP header after the header handler has been called? In PEAR::SOAP one was able to return a reference to variable that would hold the SOAP header so it could be modified after the handler returned. Ex:

    class MethodWithHeaders
    {
        public $sessionKey;
    
        /**
         * HeaderA SOAP header
         */
    
        public function &header($string)
        {
            //Return By reference so we can modify latter 
            return $this->sessionKey;
        }
    
        public function input($in)
        {
            //Null out sessionKey
            $this->sessionKey=””;
        }
    
     ....
     ....
    };
    


    In PEAR::SOAP the input method could modify the sessionKey after the header function was called because it was returned as a reference. I've tried this with the new PHP5 SOAP extension but it does not work and I can not find a way to modify the SOAP header after the header function has returned. Any ideas???????

    Thanks,

    Tony

    Re: Dynamic Assignment of the Header

    Hi Tony,

    In PHP 5's ext/soap implementation, you process the SOAP headers using one header function for each header supplied; in the header function, you should store any needed information into properties of your web service class. They can then be accessed by the method specified in the SOAP body, and changed internally if required, however the changes will not be reflected in the SOAP response header. To do that, you must return (from the header processing function) the new value of the header you want to return, eg. from my example above:

       /**
         * HeaderA SOAP header
         *
         * To process a SOAP header, create a function with the same name
    as the header's complexType.
         * Returned values will be sent back to the client as a SOAP response header.
         * This example returns the string in a response header, converted to uppercase.
         *
         * @param WrappedString $string Input string
         * @return WrappedString Capitalised string
         * @internal soapheader
         */
        public function WrappedString($string)
        {
            return new WrappedString(strtoupper($string->data));
        }
    

    If you need to use $string in the body method, store it in a class property.

    The purpose of SOAP headers is generally to provide and return information required by several methods of the same web service, but which are to be processed independently and in the same way for each method, for example authentication/session data - check whether a user's session is valid before allowing the method to execute for example, returning a header indicating whether the user had a valid session or not. As the headers are meant to be processed independently from the method, it could be considered bad programming practice to modify the header from the method. Can you provide an example where this is necessary?

    I plan to write in detail about SOAP authentication when I have more time, however here is a quick, incomplete and cut-down example of one way I do authenticated services, with the header being processed independently yet still having an effect on how the body method is executed:

    // Header allowing session key to be passed to continue existing session
    abstract class AuthenticatedService
    {
        private $authenticated;
        private $sessionKey;
        
        /**
         * Header specifying the session key to use for the transaction
         *
         * @param SessionKey $key Session key to use
         * @return Session Session details
         * @internal soapheader
         */
        public function SessionKey($key)
        {
            $key = $key->key;
            $sessions = new Sessions;
            $session = $sessions->GetSession($key);
            ...
            // Some code goes here which checks if the session key
            // supplied is valid, whether the session has expired etc.
            // and sets $this->authenticated to true or false depending
            // on the session's validity
    
            // If the session is invalid, the header is modified to 
            // reflect this, otherwise it is left unmodified
            if (!$this->authenticated)
                return $sessions->NullSession();
        }
    
        // Internal function for derived classes to check session status
        // (mot a web service header)
        protected function Authenticated()
        {
            return $this->authenticated;
        }
            
        // Get session key
        protected function GetSessionKey()
        {
            return $this->sessionKey;
        }
    }
    

    Web service methods can then derive from this class and check the authentication state before proceeding - but in the case the user is not authenticated, no changes to the header are made from the body method; they are always made from within the header processing function itself.

    Here's a service that will only add two numbers together if the user is authenticated:

    class Math extends AuthenticatedService
    {
        /**
         * Add two numbers together
         *
         * @param int $first First number to add
         * @param int $second Second number to add
         * @return int $result Result of addition
         * @internal soaprequires SessionKey
         */
        public function Add($first, $second)
        {
            if ($this->Authenticated())
                return $first + $second;
            else
                return 0;
        }
    }
    

    The caller is expected to check the returned SOAP header to make sure the session was authenticated, before looking at the result returned by the body method.

    Hope that helps!

    RE

    Hi Katy,

    Thanks for the response. If anyone is interested I did find a way to modify the soap header after the return of the header handler. There is an undocumented method that I found searching around the PHP database which allows you to override the SOAP header before the SOAP response is sent back to the client.

    http://cvs.php.net/viewvc.cgi/php-src/ext/soap/tests/server023.phpt?revision=1.2&view=markup

    Here is an example:

    <?php
    …..
    …..
    
    class SOAP_WebService
    {
        public $sessionKey;
        ….
        ….
    
    
        public function SOAP_WebService()
        {
             global $server;
        }
    
        /**
        * HeaderA SOAP header
        */
        public function header($string)
        {
            // Generate sessionKey
            $this->generateSessionKey($string)
            
            // Do not return anything, as we want to modify the header but
            // even if we did we can still override later
        }
    
        public function input($in)
        {
             global $server;
             $result = new returnType();
     
             if( $in->isReleaseSession() )
             {    
                  //Null out sessionKey
                  $this->sessionKey=’’;
              }
               
              // Set SoapHeader!
              $server->addSoapHeader(new SoapHeader
    ($SESSION_NAMESAPCE,’header’,$this->sessionKey))
    
            return $result; 
        }
        ....
        ....
        private function generateSessionKey( $sKey)
        {
              //Generate a new session key if needed
        }
    
    };
    
    
    $server = &new SoapServer(…);
    $server->setClass(“SOAP_WebService”);
    $server->handle($HTTP_RAW_POST_DATA);
    
    exit;
    ?>
    

    I’m not entirely sure I would say that modify the SOAP header after the handler is considered bad programming practice. It may be for some situations, but I have a situation where I must modify it and I’m sure there are probably countless other applications that may need to do the same.

    Thanks,

    Tony

    Re: Dynamic Assignment of the Header

    Hi Tony,

    Thanks for pointing out that useful tip - as noted in the linked file, SoapServer::addSoapHeader is also useful for creating response headers where no supplied header exists; a feature request that was raised from time to time on the dev-soap mailing list.

    Regarding programming practices, I would argue that, by definition:

    • if one web service method out of a suite has to modify headers, those headers are effectively arguments to the one method, so they would probably be better placed as such, rather than as headers.
    • if several web service methods have to modify the same headers in the same way, there should be a single codepath, which would be naturally placed in the header processing code.
    • if several web service methods have to modify the same headers in different ways using different codepaths, there is some design flaw in the application because the same header is being used for disparate purposes unique to the particular method being called, and will probably have to be interpreted differently by the caller depending on the method called, so the headers should probably be changed to be arguments to each method.

    However, I do like to be proven wrong (it's how you learn!), so I would be grateful if you could illustrate a situation where header modification from the method is needed; if there is a valid use for it, I would like to cover it in a subsequent article.

    Hi Katy,

    I keep getting the same error all the time!

    Everything works fine, and I get the wsdl.
    When I use a client soap to access the web service everything still works fine, for example:

    $client = new SoapClient('Test.wsdl');
    var_dump($client->__getFunctions());

    But the problem comes when i try to access the methods, for example:

    var_dump($client->helloWorld());

    All i get is:

    ["faultstring"]=>"Client Error"
    ["faultcode"]=>"HTTP"

    Any ideas?

    Re: Hi Katy,

    Make sure there isn't any whitespace at the start or end of your web service server. The absolute first thing SOAPClient must see back from the server when it makes a request is:

    <?xml version....>

    If there is any whitespace, you'll get a SOAP Fault. So, delete all whitespace before <?php and after ?> in your SOAP Server code, including any files you include / require from it. If you still have problems, post a link to your source code and WSDL and I'll take a look.

    I'm a medical doctor in

    I'm a medical doctor in Manisa which is a small city in Turkey.First of all my english is not very good.I apologize for my mistakes.

    We will be starting Family Doctor program in 2008.Our Ministry of Health
    made a contract with a software company to make program for doctors to record patient information and send it to the servers in Ministry of Health.The company made this program with Visual Studio 2005.We are trying send this information in Manisa Government Web site.But we're having some problems in sending complex parametres like this:

    ?xml version="1.0"?>
    SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soapenvelope">
    SOAP-ENV:Body>
    import0:HastaKaydetIstek xmlns:import0="http://schemas.saglik.gov.tr/MVS1.0.0.0/Mesaj.xsd">
    import0:KOD KodSistemKod="" KodSistemAd="" LoincKod="" LoincAd="">
    import0:ACIKLAMA
    import0:ID ANA_ID="" KOK_ID=""
    PROTOKOL_NO
    import0:ID
    import0:TARIH
    import0:GIZLILIK_DERECESI GizlilikKod="" GizlilikAd="" KodSistemKod="" KodSistemAd=""
    import0:HASTA_KAYIT
    HASTA_KAYIT_KIMLIK_BILGI
    HASTAKIMLIK TCKIMLIK_NO="" AD="" SOYAD=""
    CINSIYET CinsiyetKod="" CinsiyetAd="" KodSistemKod="" KodSistemAd=""
    BEYAN_CINSIYET CinsiyetKod="" CinsiyetAd="" KodSistemKod="" KodSistemAd=""
    ANNE_AD
    BABA_AD
    AILE_HEKIMI DIPLOMA_NO="" TCKIMLIK_NO="" AD="" SOYAD=""
    ID ANA_ID="" KOK_ID=""
    PROTOKOL_NO
    ID
    DOGUM_TARIHI
    BEYAN_DOGUM_TARIHI
    HASTA_KAYIT_KIMLIK_BILGI
    HASTA_ILETISIM_BILGI
    HASTA_ILETISIM_TIP
    ILETISIM_TIP IletisimTipKod="" IletisimTipAd="" KodSistemKod="" KodSistemAd=""
    ILETISIM_DEGER
    DURUM
    HASTA_ILETISIM_TIP
    HASTA_ILETISIM_ADR
    ADRES_TIP IletisimAdresKod="" IletisimAdresAd="" KodSistemKod="" KodSistemAd=""
    POSTA_KODU PostaKoduKod="" PostaKoduAd="" KodSistemKod="" KodSistemAd=""
    ADRES_ACIK
    IL IlKod="" IlAd="" KodSistemKod="" KodSistemAd=""
    ILCE IlceKod="" IlceAd="" KodSistemKod="" KodSistemAd=""
    ULKE UlkeKod="" UlkeAd="" KodSistemKod="" KodSistemAd=""
    DURUM
    HASTA_ILETISIM_ADR
    HASTA_ACIL_ILETISIM
    ILETISIM_BILGILERI
    ILETISIM_TIP IletisimTipKod="" IletisimTipAd="" KodSistemKod="" KodSistemAd=""
    ILETISIM_DEGER
    DURUM
    ILETISIM_BILGILERI
    KISI_AD_SOYAD
    HASTA_ACIL_ILETISIM
    HASTA_ILETISIM_BILGI
    HASTA_SOSYAL_EGITIM_BILGI
    SOSYAL_GUVENLIK_KURUM SosyalGuvenlikKurumKod="" SosyalGuvenlikKurumAd="" KodSistemKod="" KodSistemAd=""
    EGITIM_DURUM EgitimDurumKod="" EgitimDurumAd="" KodSistemKod="" KodSistemAd=""
    UYRUGU UyrukKod="" UyrukAd="" KodSistemKod="" KodSistemAd=""
    MEDENI_HAL MedeniHalKod="" MedeniHalAd="" KodSistemKod="" KodSistemAd=""
    MESLEK
    KAN_GRUB KanGrubuKod="" KanGrubuAd="" KodSistemKod="" KodSistemAd=""
    GEZICIHIZMETALIYORMU
    HASTA_SOSYAL_EGITIM_BILGI
    HASTA_ALERJI_BILGI
    ALERJI_TIP AlerjiKod="" AlerjiAd="" KodSistemKod="" KodSistemAd=""
    ALERJI_ACIKLAMA
    ALERJIDEVAMEDIYORMU
    HASTA_ALERJI_BILGI
    HASTA_VELI_BILGI
    VELI_TIP
    AKRABA AkrabaKod="" AkrabaAd="" KodSistemKod="" KodSistemAd=""
    ORGANIZASYON
    VELI_TIP
    VELI_AD_SOYAD
    VELI_ADRES
    VELI_TELEFON
    VELI_DURUM
    HASTA_VELI_BILGI
    HASTA_SOYGECMIS_BILGI
    HASTA_SOYGECMIS_HASTALIK_BILGI
    AILE_BILGI
    AKRABA_TIP AkrabaKod="" AkrabaAd="" KodSistemKod="" KodSistemAd=""
    DOGUM_TARIH
    OLUM_TARIH
    YASAM_DURUM
    AILE_BILGI
    GIZLILIK_TIP GizlilikKod="" GizlilikAd="" KodSistemKod="" KodSistemAd=""
    GENETIKHASTALIKVARMI
    TANI TaniKod="" TaniAd="" TaniReferans="" KodSistemKod="" KodSistemAd=""
    KESINLIK_DERECESI
    GERCEKLESME_YASI
    ACIKLAMA
    HASTA_SOYGECMIS_HASTALIK_BILGI
    HASTA_SOYGECMIS_RISK_BILGI
    TANI TaniKod="" TaniAd="" TaniReferans="" KodSistemKod="" KodSistemAd=""
    YAS
    RISK
    NEDEN
    HASTA_SOYGECMIS_RISK_BILGI
    HASTA_SOYGECMIS_BILGI
    HASTA_BEBEKLIK_BILGI
    DOGUM_AGIRLIK
    AGIRLIK_TIP AgirlikBirimKod="" AgirlikBirimAd="" KodSistemKod="" KodSistemAd=""
    DOGUM_BOY
    DOGUM_BASCEVRE
    UZUNLUK_BIRIM UzunlukBirimKod="" UzunlukBirimAd="" KodSistemKod="" KodSistemAd=""
    FENIL_KAN_ALINDIMI
    DOGUM_KOMPLIKASYONU_VARMI
    EK_GIDAYA_BASLAMA_AYI
    HASTA_BEBEKLIK_BILGI
    HASTA_KADIN_BILGI
    EVLENME_YASI
    ILK_GEBELIK_YASI
    CANLI_DOGUM_SAYISI
    OLU_DOGUM_SAYISI
    DUSUK_DOGUM_SAYISI
    KONJ_ANOMALI
    SERVIKAL_SMEAR
    AP_DANISMANLIGI
    HASTA_KADIN_BILGI
    HASTA_DURUM_BILGI HastaKayitDurumKod="" HastaKayitDurumAd="" KodSistemKod="" KodSistemAd=""
    import0:HASTA_KAYIT
    import0:KULLANICI TCKIMLIK_NO="" AD="" SOYAD=""
    KURUM_ILCE IlceKod="" IlceAd="" KodSistemKod="" KodSistemAd=""
    KURUM_IL IlKod="" IlAd="" KodSistemKod="" KodSistemAd=""
    KATILIM_TIP KATILIM_TIP_KOD="" KATILIM_TIP_AD=""
    import0:KULLANICI
    import0:HastaKaydetIstek
    SOAP-ENV:Body
    SOAP-ENV:Envelope

    We can pass simple parameters like this:

    ?xml version="1.0"?
    SOAP-ENV:Envelope xmlns:SOAP-ENV="http:/schemas.xmlsoap.org/soap/envelope/"
    SOAP-ENV:Body
    import0:KullaniciDogrulaIstek xmlns:import0="http://schemas.saglik.gov.tr/MVS/1.0.0.0/IslemlerMesaj.xsd"
    import0:KullaniciKimlikNo
    import0:Sifre
    import0:KullaniciDogrulaIstek
    SOAP-ENV:Body
    SOAP-ENV:Envelope

    We think to send the information like array in array.How can we do this?
    We need help.Thank you.

    Re: I'm a medical doctor in

    To give a meaningful reply more information is needed: what languages are the client and server written in? What error message do you get? Where is your WSDL file? Can you supply a properly formatted SOAP payload that is populated with parameters?

    Best regards,

    Katy.

    a woman?

    brother, respect. what has intelligence to do with gender.

    Re: a woman?

    I could write a reply to that but my answer would be somewhat biassed :-)