I need to generate the following XML
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<SOAP-ENV:Body>
<ns1:submitGetHistoryRequest>
<ns1:headers>
<ns1:daterange>
<ns1:period>
<ns1:start>2018-05-08</ns1:start>
<ns1:end>2018-05-08</ns1:end>
</ns1:period>
</ns1:daterange>
</ns1:headers>
<ns1:fields>
<ns1:field>PX_LAST</ns1:field>
</ns1:fields>
<ns1:instruments>
<ns1:instrument>
<ns1:id>US0000000002</ns1:id>
<ns1:yellowkey>Equity</ns1:yellowkey>
<ns1:type>ISIN</ns1:type>
</ns1:instrument>
<ns1:instrument>
<ns1:id>US0000000001</ns1:id>
<ns1:yellowkey>Equity</ns1:yellowkey>
<ns1:type>ISIN</ns1:type>
</ns1:instrument>
</ns1:instruments>
</ns1:submitGetHistoryRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I use PHP 7.1.17 and SoapClient.
I can not pass options to SoapClient, as the instrument key is repeated and PHP's associated array can not have same key twice. I tried constructing object and setting instrument properties as SoapVar, but it generates incorrect XML. Here is code and result:
$options = new \stdClass();
$options->headers = new \stdClass();
$options->headers->daterange = new \stdClass();
$options->headers->daterange->period = new \stdClass();
$options->headers->daterange->period->start = '2018-05-08';
$options->headers->daterange->period->end = '2018-05-08';
$options->fields = new \stdClass();
$options->fields->field = 'PX_LAST';
//first instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000002';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments[] = new \SoapVar(
$instrument,
SOAP_ENC_OBJECT,
'stdClass',
"http://soapinterop.org/xsd",
"instrument"
);
//second instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000001';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments[] = new \SoapVar(
$instrument,
SOAP_ENC_OBJECT,
'stdClass',
"http://soapinterop.org/xsd",
"instrument"
);
<ns1:instruments/> remains empty in resulting XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<SOAP-ENV:Body>
<ns1:submitGetHistoryRequest>
<ns1:headers>
<ns1:daterange>
<ns1:period>
<ns1:start>2018-05-08</ns1:start>
<ns1:end>2018-05-08</ns1:end>
</ns1:period>
</ns1:daterange>
</ns1:headers>
<ns1:fields>
<ns1:field>PX_LAST</ns1:field>
</ns1:fields>
<ns1:instruments/>
</ns1:submitGetHistoryRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
How can I pass options to SoapClient, to generate XML with repeated instrument keys?
I solved this. Turns out when you pass an ordered array (not associative one) as object's property, as many XML nodes are generated using that property's name, as number of elements in the array. So instead of building SoapVar objects and putting them into instruments[] array, I just assigned array of instruments to instruments as instrument property:
$options->instruments = new \stdClass();
//first instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000002';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments->instrument[] = $instrument;
//second instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000001';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments->instrument[] = $instrument;
I build instruments in a foreach loop. Btw converting array to object instead of building stdClass also works fine:
$options->instruments->instrument[] = (object)[
'id' => 'US0000000001',
'type' => 'ISIN',
'yellowkey' => 'Equity'
]
Related
I am struggling in adding an attribute to a SoapVar-Element.
This is the structure i want to creat:
<SOAP-ENV:Body>
<ns:ServiceRequest>
<ns:Method>PING</ns:Method>
<ns:Property Name="name1">foo</ns:Property>
<ns:Property Name="name2">bar</ns:Property>
</ns:ServiceRequest>
</SOAP-ENV:Body>
but this is all i get:
<SOAP-ENV:Body>
<ns1:ServiceRequest>
<ns1:Method>PING</ns1:Method>
<ns1:Property>foo</ns1:Property>
<ns1:Property>bar</ns1:Property>
</ns1:ServiceRequest>
</SOAP-ENV:Body>
This is my code to create one of the "Property"-nodes:
$node = new SoapVar( 'foo', XSD_STRING, null, null, 'Property', $namespace);
I already tried replacing the 'foo' with an array or an object but nothing worked.
$Property['_'] = 'foo';
$Property['Name'] = 'name1';
$node = new SoapVar( $Property, SOAP_ENC_OBJECT);
... which results in:
<_>foo</_>
<Name>name1</Name>
Let me know if you need more information
I can't get this to work. I've read a bunch on it on the forum already but I just can't seem to find the solution to this.
I've created a SOAP call and it's working etc., but when I try to pass the same parameters multiple times it just overwrites itself which is logical.
The code has to be done with objects only so I've used stdClass()
Example of the code below:
$relationCreate = new stdClass();
$relationCreate->credentials = new stdClass();
$relationCreate->credentials->ApiKey = ''; //Removed for security reasons.
$relationCreate->credentials->DatabaseId = ''; //Removed for security reasons.;
$relationCreate->credentials->UserId = ''; //Removed for security reasons.;
$relationCreate->parentRelationId = $company;
$relationCreate->relationEntityTypeId = "84a15869-5b88-49df-ad47-7b6f9648ae07";
//surname
$relationCreate->relationFieldValues = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData->Id = "9d549512-dc8a-4774-84d1-27a349e8a8c7";
$relationCreate->relationFieldValues->PvFieldValueData->Value = $name;
// This one has to repeat which does not work. Which is logical
$relationCreate->relationFieldValues = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData->Id = "9d549512-dc8a-4774-84d1-27a349e8a8c7";
$relationCreate->relationFieldValues->PvFieldValueData->Value = $name;
The soap should look as followed I tested this using SoapUI:
<api:fieldValues>
<!--Zero or more repetitions:-->
<api:PvFieldValueData>
<api:Id>c2fcb464-92e6-4227-8672-56f88e219279</api:Id>
<!--Optional:-->
<api:Value>Test</api:Value>
</api:PvFieldValueData>
</api:fieldValues>
<api:fieldValues>
<!--Zero or more repetitions:-->
<api:PvFieldValueData>
<api:Id>d900fe23-8549-451c-82f4-c5918cb3abbb</api:Id>
<!--Optional:-->
<api:Value>Test</api:Value>
</api:PvFieldValueData>
</api:fieldValues>
WSDL file for reference: https://api.perfectview.nl/V1/perfectview.asmx?WSDL
References:
PHP SoapClient - Multiple attributes with the same key
SoapClient: how to pass multiple elements with same name?
You can try to put the items into an array.
Example:
$relationCreate->relationFieldValues = [];
// repeat this in a foreach loop:
$item = new stdClass();
$item->PvFieldValueData = new stdClass();
$item->PvFieldValueData->Id = $uuid;
$item->PvFieldValueData->Value = $name;
// Add item to values
$relationCreate->relationFieldValues[] = $item;
The SOAP API I am using, needs the request XML formatted as below:
<SOAP-ENV:Body>
<ns1:functionName/>
<UserID>WEB</UserID>
<Attribute>
<ID>83</ID>
<Value>34343</Value>
</Attribute>
<Attribute>
<ID>84</ID>
<Value>45343</Value>
</Attribute>
</SOAP-ENV:Body>
I have gone through almost all "multiple element" related questions here on StackOverflow but still can't figure it out.
Here is what I am trying at the moment:
$args = new ArrayObject();
$args->UserID = WEB;
$Attribute = new stdClass();
$Attribute->ID = 83;
$Attribute->Value = 34343;
$args->append(new SoapParam($Attribute, 'Attribute'));
$Attribute = new stdClass();
$Attribute->ID = 84;
$Attribute->Value = 45343;
$args->append(new SoapParam($Attribute, 'Attribute'));
$soapClient->functionName($args);
Can someone please help me out with this?
I would advise you to use a WSDL to php generator as you'll deal with abstracted classes that match the required parameter and the operations so you won't have to figure out the correct syntax, it will be automaticcally done by the generated package.
Two generators:
Mine: https://github.com/WsdlToPhp/PackageGenerator
From others: https://github.com/wsdl2phpgenerator/wsdl2phpgenerator
Good luck
Finally managed to figure it out. Hope the below code helps someone:
$args = array();
$args[] = new SoapVar('WEB', XSD_STRING, null, null, 'UserID');
$obj = new stdClass();
$obj->ID = 83;
$obj->Value = 34343;
$args[] = new SoapVar($obj, SOAP_ENC_OBJECT, null, null, 'Attribute');
$obj = new stdClass();
$obj->ID = 84;
$obj->Value = 45343;
$args[] = new SoapVar($obj, SOAP_ENC_OBJECT, null, null, 'Attribute');
$soapClient->functionName(new SoapVar($args, SOAP_ENC_OBJECT));
I am trying to create this :
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<AccessKey xmlns="http://eatright/membership" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Value>67a4ef47-9ddf-471f-b6d0-0000c28d57d1</Value>
</AccessKey>
</s:Header>
<s:Body>
<WebUserLogin xmlns="http://eatright/membership">
<loginOrEmail>1083790</loginOrEmail>
<password>thomas</password>
</WebUserLogin>
</s:Body>
</s:Envelope>
I created this PHP code
class ChannelAdvisorAuth
{
public $AccessKey ;
public function __construct($key)
{
$this->AccessKey = $key;
}
}
$AccessKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$url = "http://ws.eatright.org/service/service.svc?wsdl";
$client = new SoapClient($url, array("trace" => 1, "exception" => 0));
$auth = new ChannelAdvisorAuth($AccessKey);
$header = new SoapHeader("AccessKey", "Value", $AccessKey, false);
$client->__setSoapHeaders($header);
$result = $client->ValidateAccessKey();
echo "REQUEST:\n" . $client->__getLastRequest() . "\n";
The output of the above PHP code is :
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://eatright/membership" xmlns:ns2="AccessKey">
<SOAP-ENV:Header>
<ns2:Value>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</ns2:Value>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:ValidateAccessKey/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
How to change the PHP code to output the XML as requested by web service provider?
How to replace the "SOAP-ENV" to "S"?
Is there is a way to remove the NS1 and NS2? and also adjust the whole format of the XML to meet the requirements? thanks
You don't need to worry about SOAP-ENV, ns1 or ns2 - they are just prefixes referring to the namespaces. As long as the full namespaces are correct, it's going to be alright.
I think the SOAP header should be made like this:
$access_key = new stdClass();
$access_key->Value = 'XXX';
$hdr = new SoapHeader('http://eatright/membership', 'AccessKey', $access_key);
$client->__setSoapHeaders($hdr);
I don't see a purpose of xmlns:i in the first example - there are no elements having XSI attributes.
I'm not sure what to do with the body. In your first example, there is a call to the WebUserLogin operation, while in your PHP code you are trying to call ValidateAccessKey.
Have you tried reading the WSDL file which is pointed by $url
Ok I found the problem and I will add it here in case someone looking for same issue.
$access_key = new stdClass();
$access_key->Value = 'xxxxxxxxxxxxxxxxxxx';
// Create the SoapClient instance
$url = "http://ws.eatright.org/service/service.svc?wsdl";
$client = new SoapClient($url, array("trace" => 1, "exception" => 0));
$hdr = new SoapHeader('http://eatright/membership', 'AccessKey', $access_key);
$client->__setSoapHeaders($hdr);
$soapParameters = array('loginOrEmail ' => $username, 'password' => $password);
$login = new stdClass();
$login->loginOrEmail='LoginID';
$login->password='Password';
$result = $client->WebUserLogin($login);
The problem is that I cannot succeed to send an array of class through SOAP to a specific web service that I cannot change his structure.
Here below you'll see the schema of the Soap function:
http://www.elyotech.com/share/yoni/forum/developpeznet-soap.jpg
Here you'll find the code I'm corresponding to it:
$s = new soapclient($URL_WEBSERVICE,array('wsdl'=>true,"trace"=>true));
$params = new stdClass();
$params->loginInfo = new stdClass();
$params->loginInfo->UserName = 'username';
$params->loginInfo->Password = 'password';
$params->loginInfo->LanguageCode = 'en';
$params->reservation = new stdClass();
$params->reservation->EmailRecipient2 = 'yonia#yopmail.com';
$params->reservation->EmailRecipient3 = 'yonia2#yopmail.com';
$params->reservation->FirstName = 'Yoni'
foreach($extras as $id=>$extra)
{
$params->Extras[$id]= new stdClass();
$params->Extras[$id]->SelectedExtra = new stdClass();
$params->Extras[$id]->ExtensionData = new stdClass();
$params->Extras[$id]->SelectedExtra->Amount = 1;
$params->Extras[$id]->SelectedExtra->ID = $extra;
}
Here is the SOAP request that is sent:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/">
<SOAP-ENV:Body>
<ns1:CreateReservation>
<ns1:loginInfo>
<ns1:UserName>monusername</ns1:UserName>
<ns1:Password>monpass</ns1:Password>
<ns1:LanguageCode>en</ns1:LanguageCode>
</ns1:loginInfo>
<ns1:reservation>
<ns1:EmailRecipient2>yonia#yopmail.com</ns1:EmailRecipient2>
<ns1:EmailRecipient3>yonia2#yopmail.com</ns1:EmailRecipient3>
<ns1:FirstName>Yoni</ns1:FirstName>
</ns1:reservation>
</ns1:CreateReservation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
In this Soap request, I cannot find the Extras array of objects.
Do you have any idea of how I should create my object in order to send it correctly?