Hi I'm getting an error:
no operations defined in the WSDL document!
I'm searching all possible ways that might answer my problem for almost a week but no luck I can't find it. I use nusoap library and here's my code:
<?php
include_once('lib/nusoap.php');
$username = 'xxxxx#username.com';
$password = 'xxxxxxx';
$endpoint = 'https://mail.xxxxxxxxx.com/ews/services.wsdl';
$wsdl = true;
$soapclient = new nusoap_client($endpoint, $wsdl);
$xml = '<wsdl:definitions targetNamespace="http://schemas.microsoft.com/exchange/services/2006/messages">';
$xml .= '<wsdl:message name="UploadItemsSoapIn">';
$xml .= '<wsdl:part name="request" element="tns:UploadItems"/>';
$xml .= '<wsdl:part name="Impersonation" element="t:ExchangeImpersonation"/>';
$xml .= '<wsdl:part name="MailboxCulture" element="t:MailboxCulture"/>';
$xml .= '<wsdl:part name="RequestVersion" element="t:RequestServerVersion"/>';
$xml .= '</wsdl:message>';
$xml .= '</wsdl:definitions>';
$operation = 'UploadItemsSoapIn';
$result = $soapclient->call($operation,$xml);
$soapclient->setCredentials($username, $password, 'ntlm');
if ($soapclient->fault) {
echo '<h2>Fault (Expect - The request contains an invalid SOAP body)</h2><pre>'; print_r($result); echo '</pre>';
} else {
$err = $soapclient->getError();
if ($err) {
echo '<h2>Error</h2><pre>' . $err . '</pre>';
} else {
echo '<h2>Result</h2><pre>'; print_r($result); echo '</pre>';
}
}
and this is the view in services.wsdl link:
<wsdl:definitions targetNamespace="http://schemas.microsoft.com/exchange/services/2006/messages">
<wsdl:types>
<xs:schema>
<xs:import namespace="http://schemas.microsoft.com/exchange/services/2006/messages" schemaLocation="messages.xsd"/>
</xs:schema>
</wsdl:types>
<wsdl:message name="UploadItemsSoapIn">
<wsdl:part name="request" element="tns:UploadItems"/>
<wsdl:part name="Impersonation" element="t:ExchangeImpersonation"/>
<wsdl:part name="MailboxCulture" element="t:MailboxCulture"/>
<wsdl:part name="RequestVersion" element="t:RequestServerVersion"/>
</wsdl:message>
<wsdl:message name="UploadItemsSoapOut">
<wsdl:part name="UploadItemsResult" element="tns:UploadItemsResponse"/>
<wsdl:part name="ServerVersion" element="t:ServerVersionInfo"/>
</wsdl:message>
Sorry I'm just a newbie in soap. All I want is just to run the basic function and just display email or names of the login user. Thanks in advance!
Related
I want my php-script to download files from a specific link based on xml id's. I want it to ignore the rest of the xml-code, I want it to just look at the first id of every lib.
My xml looks like this:
**
<lib id="ITEM_I_WANT_TO_DOWNLOAD_1" revision="0000">
<part id="0000" type="ch"/>
<part id="0000" type="ls"/>
<part id="0000" type="rs"/>
<part id="0000" type="ch"/>
</lib>
<lib id="ITEM_I_WANT_TO_DOWNLOAD_2" revision="0000">
<part id="0000" type="ch"/>
<part id="0000" type="ls"/>
<part id="0000" type="rs"/>
<part id="0000" type="ch"/>
</lib>
**
My current PHP-script looks like this:
if (!defined('STDIN'))
{
echo 'Please run it as a cmd ({path to your php}/php.exe {path to badges.php} -f)';
exit;
}
define('BASE', 'https://randomtarget.com/');
$figuremap = get_remote_data('https://random/xmlfile-needed.xml/');
if (!file_exists('C:/outputfolder/')) {
mkdir('C:/outputfolder/', 0777, true);
echo "\n --------------> Output folder has been made... \n";
sleep(3);
$fp = fopen("C:/downloaded-xmlfile.xml", "w");
fwrite($fp, $figuremap);
fclose($fp);
echo "\n --------------> XML downloaded and placed into folder \n";
sleep(3);
}
$pos = 0;
while ($pos = strpos($figuremap, '<lib id="', $pos +1))
{
$pos1 = strpos($figuremap, '"', $pos);
$rule = substr($figuremap, $pos, ($pos1 -$pos));
$rule = explode(',', $rule);
$revision = str_replace('">', '', $rule[1]);
$clothing_file = current(explode('*', str_replace('"', '', $rule[2])));
if (file_exists('C:/outputfolder/'.$clothing_file.'.swf'))
{
echo 'Clothing_file found: '.$clothing_file."\r\n";
continue;
}
echo 'Download clothing_file: '.$clothing_file.' '.$revision."\r\n";
if (!#copy(BASE.'/'.$revision.'/'.$clothing_file.'.swf', 'C:/outputfolder'.$clothing_file.'.swf'))
{
echo 'Error downloading: '.$clothing_file."\r\n";
}
}
Beside this code I wrote a get_remote_data function so that's allright. I just want the strpos to grab all the id='' items to check if the files exist on the target-site.
How can I fix it?
There are some easy ways of processing XML files, the easiest (but less flexible) is SimpleXML, the following code should replace the main processing loop...
$xml = simplexml_load_string($figuremap);
foreach ( $xml->lib as $lib ) {
$clothing_file = (string) $lib['id'];
if (file_exists('C:/outputfolder/'.$clothing_file.'.swf'))
{
echo 'Clothing_file found: '.$clothing_file."\r\n";
continue;
}
echo 'Download clothing_file: '.$clothing_file.' '.$revision."\r\n";
if (!#copy(BASE.'/'.$revision.'/'.$clothing_file.'.swf', 'C:/outputfolder'.$clothing_file.'.swf'))
{
echo 'Error downloading: '.$clothing_file."\r\n";
}
}
The start point is to load the XML you have in $figuremap into SimpleXML, then to loop over the elements. This assumes an XML structure of something like...
<lib1>
<lib id="ITEM_I_WANT_TO_DOWNLOAD_1" revision="0000">
<part id="0000a" type="ch" />
<part id="0000" type="ls" />
<part id="0000" type="rs" />
<part id="0000" type="ch" />
</lib>
<lib id="ITEM_I_WANT_TO_DOWNLOAD_2" revision="0000">
<part id="00001" type="ch" />
<part id="0000" type="ls" />
<part id="0000" type="rs" />
<part id="0000" type="ch" />
</lib>
</lib1>
The actual name of the base element doesn't matter as long as the <lib> elements are 1 level down then you can use $xml->lib to loop over them.
Your posted xml string is actually invalid. It needs to be wrapped in a parent element to be repaired. I'm not sure if you are posting your exact xml string or just a section of it.
$xml = '<lib id="ITEM_I_WANT_TO_DOWNLOAD_1" revision="0000">
<part id="0000" type="ch"/>
<part id="0000" type="ls"/>
<part id="0000" type="rs"/>
<part id="0000" type="ch"/>
</lib>
<lib id="ITEM_I_WANT_TO_DOWNLOAD_2" revision="0000">
<part id="0000" type="ch"/>
<part id="0000" type="ls"/>
<part id="0000" type="rs"/>
<part id="0000" type="ch"/>
</lib>';
$xml = '<mydocument>' . $xml . '</mydocument>'; // repair invalid xml
https://stackoverflow.com/q/4544272/2943403
$doc = new DOMDocument();
$doc->loadXml($xml);
$xpath = new DOMXpath($doc);
foreach ($xpath->evaluate('//lib/#id') as $attr) {
$clothing_file = $attr->value;
// perform your conditional actions ...
}
//lib/#id says search for the id attribute of all <lib> elements, anywhere in the document.
I'm trying to implement a simple webservice using nusoap.
Server:
<?php
require_once "nusoaplib/nusoap.php";
class food {
public function getFood($type) {
switch ($type) {
case 'starter':
return 'Soup';
break;
case 'Main':
return 'Curry';
break;
case 'Desert':
return 'Ice Cream';
break;
default:
break;
}
}
}
$server = new soap_server();
$server->configureWSDL("foodservice", "urn:foodservice");
$server->register("food.getFood",
array("type" => "xsd:string"),
array("return" => "xsd:string"),
"urn:foodservice",
"urn:foodservice#getFood",
"rpc",
"encoded",
"Get food by type");
#$server->service($HTTP_RAW_POST_DATA);
?>
Client:
<?php
require_once "nusoaplib/nusoap.php";
$client = new nusoap_client("http://localhost/SOAPServer.php?wsdl", true);
$error = $client->getError();
if ($error) {
echo "<h2>Constructor error</h2><pre>" . $error . "</pre>";
}
$result = $client->call("food.getFood", array("type" => "Main"));
if ($client->fault) {
echo "<h2>Fault</h2><pre>";
print_r($result);
echo "</pre>";
} else {
$error = $client->getError();
if ($error) {
echo "<h2>Error</h2><pre>" . $error . "</pre>";
} else {
echo "<h2>Main</h2>";
echo $result;
}
}
// show soap request and response
echo "<h2>Request</h2>";
echo "<pre>" . htmlspecialchars($client->request, ENT_QUOTES) . "</pre>";
echo "<h2>Response</h2>";
echo "<pre>" . htmlspecialchars($client->response, ENT_QUOTES) . "</pre>";
?>
The wsdl file is generated by nusoap, which is the following:
<definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="urn:foodservice" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="urn:foodservice">
<types>
<xsd:schema targetNamespace="urn:foodservice">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/"/>
</xsd:schema>
</types>
<message name="food.getFoodRequest">
<part name="type" type="xsd:string"/>
</message>
<message name="food.getFoodResponse">
<part name="return" type="xsd:string"/>
</message>
<portType name="foodservicePortType">
<operation name="food.getFood">
<documentation>Get food by type</documentation>
<input message="tns:food.getFoodRequest"/>
<output message="tns:food.getFoodResponse"/>
</operation>
</portType>
<binding name="foodserviceBinding" type="tns:foodservicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="food.getFood">
<soap:operation soapAction="urn:foodservice#getFood" style="rpc"/>
<input>
<soap:body use="encoded" namespace="urn:foodservice" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="urn:foodservice" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="foodservice">
<port name="foodservicePort" binding="tns:foodserviceBinding">
<soap:address location="http://10.152.128.39/SOAPServer.php"/>
</port>
</service>
</definitions>
When accessing both the server file and the wsdl file, they both work, but I get the error message when I try to access the client:
[faultcode] => SOAP-ENV:Client
[faultactor] =>
[faultstring] => error in msg parsing:
xml was empty, didn't parse!
[detail] =>
Any suggestions what could be the problem?
In your nusoap. Server you should change:
This:
#$server->service($HTTP_RAW_POST_DATA);
for this:
#$server->service(file_get_contents("php://input"));
You may remove the # if you want to check notices and warnings.
Some explanation from http://php.net/manual/en/ini.core.php#ini.always-populate-raw-post-data
This feature was DEPRECATED in PHP 5.6.0, and REMOVED as of PHP 7.0.0.
If set to TRUE, PHP will always populate the $HTTP_RAW_POST_DATA containing the raw POST data. Otherwise, the variable is populated only when the MIME type of the data is unrecognised.
The preferred method for accessing raw POST data is php://input, and $HTTP_RAW_POST_DATA is deprecated in PHP 5.6.0 onwards. Setting always_populate_raw_post_data to -1 will opt into the new behaviour that will be implemented in a future version of PHP, in which $HTTP_RAW_POST_DATA is never defined.
Regardless of the setting, $HTTP_RAW_POST_DATA is not available with enctype="multipart/form-data".
I am building a service against Sonos' Music API (SMAPI). Sometimes I have to send back a response in the following format:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>Client.NOT_LINKED_RETRY</faultcode>
<faultstring>Link Code not found retry...</faultstring>
<detail>
<ExceptionInfo>NOT_LINKED_RETRY</ExceptionInfo>
<SonosError>5</SonosError>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
I am building my service using the PHP SOAP library and for the above response I tried throwing a SoapFault like this:
throw new SoapFault('Client.NOT_LINKED_RETRY', 'Link Code not found retry...');
But when I try this the response that is sent back looks like this:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>Client.NOT_LINKED_RETRY</faultcode>
<faultstring>Link Code not found retry...</faultstring>
<detail>
<SonosError/>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Notice that there is no ExceptionInfo and that SonosError is empty. Is it possible to set ExceptionInfo and SonosError using SoapFault? I tried all kinds of things, but couldn't get it working, so as a work around I am doing this now:
http_response_code(500);
header("Content-type: text/xml");
$ret = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$ret .= '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">';
$ret .= '<SOAP-ENV:Body>';
$ret .= '<SOAP-ENV:Fault>';
$ret .= '<faultcode>Client.NOT_LINKED_RETRY</faultcode>';
$ret .= '<faultstring>Link Code not found retry...</faultstring>';
$ret .= '<detail>';
$ret .= '<ExceptionInfo>NOT_LINKED_RETRY</ExceptionInfo>';
$ret .= '<SonosError>5</SonosError>';
$ret .= '</detail>';
$ret .= '</SOAP-ENV:Fault>';
$ret .= '</SOAP-ENV:Body>';
$ret .= '</SOAP-ENV:Envelope>'."\n";
echo $ret; exit;
Not sure if it's relevant but the WSDL can be found here.
Update: when I try the suggestion below like this:
$detail = new StdClass();
$detail->SonosError = 5;
$detail->ExceptionInfo = 'NOT_LINKED_RETRY';
throw new SoapFault(
'Client.NOT_LINKED_RETRY',
'Link Code not found retry...',
NULL,
$detail
);
I get:
<detail>
<customFault>
<SonosError>5</SonosError>
<ExceptionInfo>NOT_LINKED_RETRY</ExceptionInfo>
</customFault>
</detail>
This is almost what I need, except for <customFault> tag. Is there a way to get rid of it and have SonosError and ExceptionInfo in <detail> directly?
The fact that you don't see the ExceptionInfo tag is because it is not defined in the wsdl. On the other hand SonosError is defined.
First thing first, in order to fill the SonosError you have to pass the arguments.
From here you can see that the constructor has more parameters
SoapFault('code', 'string', 'actor', 'detail', 'name', 'header');
In order to pass the SonosError call it like this
$detail = new StdClass();
$detail->SonosError = 5;
throw new SoapFault('Client.NOT_LINKED_RETRY', 'Link Code not found retry...', null, $details);
As for the ExceptionInfo, the wsdl must be changed. As it is now, the details tag is represented by this sections
<wsdl:message name="customFault">
<wsdl:part name="customFault" element="tns:SonosError"/>
</wsdl:message>
<xs:element name="SonosError" type="xs:int"/>
If you change the above sections with these, you will have what you need.
<wsdl:message name="customFault">
<wsdl:part name="customFault" type="tns:customFaultType" />
</wsdl:message>
<xs:complexType name="customFaultType">
<xs:sequence>
<xs:element name="SonosError" type="xs:int"/>
<xs:element name="ExceptionInfo" type="xs:string"/>
</xs:sequence>
</xs:complexType>
And of course you add the parameter and the array becomes like this
$detail = new StdClass();
$detail->SonosError = 5;
$detail->ExceptionInfo = 'NOT_LINKED_RETRY';
how to validate a xml file against a xsd? there is domdocument::schemaValidate() but It does not tell where are the errors. is there any class for that? does it have any worth making that parser from scratch? or is it just reinventing he wheel,
This code does the business:
$xml= new DOMDocument();
$xml->loadXML(<A string goes here containing the XML data>, LIBXML_NOBLANKS); // Or load if filename required
if (!$xml->schemaValidate(<file name for the XSD file>)) // Or schemaValidateSource if string used.
{
// You have an error in the XML file
}
See the code in http://php.net/manual/en/domdocument.schemavalidate.php To retrieve the errors.
I.e.
justin at redwiredesign dot com 08-Nov-2006 03:32 post.
User contrib from http://php.net/manual/en/domdocument.schemavalidate.php
It works like a charm!
For more detailed feedback from DOMDocument::schemaValidate, disable
libxml errors and fetch error information yourself. See
http://php.net/manual/en/ref.libxml.php for more info.
example.xml
<?xml version="1.0"?>
<example>
<child_string>This is an example.</child_string>
<child_integer>Error condition.</child_integer>
</example>
example.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="example">
<xs:complexType>
<xs:sequence>
<xs:element name="child_string" type="xs:string"/>
<xs:element name="child_integer" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
PHP
<?php
function libxml_display_error($error)
{
$return = "<br/>\n";
switch ($error->level) {
case LIBXML_ERR_WARNING:
$return .= "<b>Warning $error->code</b>: ";
break;
case LIBXML_ERR_ERROR:
$return .= "<b>Error $error->code</b>: ";
break;
case LIBXML_ERR_FATAL:
$return .= "<b>Fatal Error $error->code</b>: ";
break;
}
$return .= trim($error->message);
if ($error->file) {
$return .= " in <b>$error->file</b>";
}
$return .= " on line <b>$error->line</b>\n";
return $return;
}
function libxml_display_errors() {
$errors = libxml_get_errors();
foreach ($errors as $error) {
print libxml_display_error($error);
}
libxml_clear_errors();
}
// Enable user error handling
libxml_use_internal_errors(true);
$xml = new DOMDocument();
$xml->load('example.xml');
if (!$xml->schemaValidate('example.xsd')) {
print '<b>DOMDocument::schemaValidate() Generated Errors!</b>';
libxml_display_errors();
}
?>
This is a complete code snippet for displaying xsd validation errors:
$xml = '<test/>';
$xsd = '/path/to/xsd';
// needed for getting errors
libxml_use_internal_errors(true);
$domDocument= new DOMDocument();
$domDocument->loadXML($xml);
if (!$domDocument->schemaValidate($xsd)) {
$errors = libxml_get_errors();
foreach ($errors as $error) {
print_r($error);
}
libxml_clear_errors();
}
I am trying to connect a wsdl service. Other methods don't work without login. But when I tried the login I got a httpheaders error. My wsdl link : http://dgpysws.teias.gov.tr/dgpys/services/EVDServis?wsdl
when i look this link=
http://dgpysws.teias.gov.tr/dgpys/services/EVDServis.wsdl
<xs:element name="login">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="loginMessage" nillable="true" type="dgp:LoginMessage"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="LoginMessage">
<xs:sequence>
<xs:element minOccurs="0" name="Password" nillable="true" type="dgp:StringValue"/>
<xs:element minOccurs="0" name="UserName" nillable="true" type="dgp:StringValue"/>
</xs:sequence>
</xs:complexType>
Here is my php code;
<?php
// Turn up error reporting
ini_set ("display_errors", "1");
error_reporting (E_ALL|E_STRICT);
// Turn off WSDL caching
ini_set ('soap.wsdl_cache_enabled', 0);
$Password = 'deneeme';
$UserName = 'demnenee';
$search_query = new StdClass();
$search_query->oLoginRequest = new StdClass();
$search_query->oLoginRequest->Password = $Password;
$search_query->oLoginRequest->Username = $UserName;
echo "Setting up SOAP options\n";
$soap_options = array(
'trace' => 1, // traces let us look at the actual SOAP messages later
'exceptions' => 1 );
$wsdl = "http://dgpysws.teias.gov.tr/dgpys/services/EVDServis?wsdl";
echo "Checking SoapClient exists\n";
echo '<br>';
if (!class_exists('SoapClient'))
{
die ("You haven't installed the PHP-Soap module.");
}
echo "Creating webservice connection to $wsdl\n";
$webservice = new SoapClient($wsdl,$soap_options);
try {
$result = $webservice->login($search_query);
// perform some logic, output the data to Asterisk, or whatever you want to do with it.
} catch (SOAPFault $f) {
// handle the fault here
echo 'Hata:' . $f;
}
echo "Script complete\n\n";
?>
I am getting this error when run php file;
Setting up SOAP options Checking SoapClient exists
Creating webservice connection to http://dgpysws.teias.gov.tr/dgpys/services/EVDServis?wsdl Hata:SoapFault exception: [HTTP] Error Fetching http headers in C:\xampp\htdocs\test\pmum.php:36 Stack trace: #0 [internal function]: SoapClient->__doRequest('__call('login', Array) #2 C:\xampp\htdocs\test\pmum.php(36): SoapClient->login(Object(stdClass)) #3 {main}Script complete
$client = new SoapClient("http://dgpysws.teias.gov.tr/dgpys/services/EVDServis.wsdl");
$p1->loginMessage->UserName->v = "Deneme";
$p1->loginMessage->Password->v = "Deneme";
$deneme = $client->login($p1);
var_dump($deneme);
worked for me!