php soapserver returning better readable associative array - php

I'm using PHP SOAPSERVER class.
As a response I'm sending associative php array:
function getItems()
{
...
$items[] = Array("itemID" =>$itemID,"itemName"=>$itemName);
return $items;
}
SOAP return is like this:
...
<Items>
<item type="Map">
<item>
<key type="string">
itemID
</key>
<value type="string">
17558
</value>
</item>
<item>
<key type="string">
itemName
</key>
<value type="string">
I-17558
</value>
</item>
</item>
</Items>
...
Such return is pretty hard to analyze for human (given bigger array).
The preferred form would be like this:
...
<Items>
<item>
<itemID>17558</itemID>
<itemName>I-17558</itemName>
</item>
<item>
<itemID>17559</itemID>
<itemName>I-17559</itemName>
</item>
</Items>
...
Is such SOAP return possible (not changing the return type - array)? How?
I have just started with SOAP and most tutorials show how to return simple types like string.

Instead of sending an associative array, send a stdclass object.
Example :
$return = new stdclass;
$return->ItemID = 1;
$return->ItemName = 'foo';
return $return;
Then the SOAP results will be just the way you want it!

Related

How to parse soap xml response that have several namespaces defined. I need to parse the Articles array returned

The soap xml reponse is as such:
<SOAP-ENV:Envelope 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/">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:NS1="urn:TPAPIPosIntfU-ITPAPIPOS">
<NS1:GetArticlesInfoResponse xmlns:NS2="urn:TPAPIPosIntfU" xmlns:NS3="urn:TPAPIPosTypesU">
<return xsi:type="NS2:TGetArticlesInfoResponse">
<ReturnCode xsi:type="xsd:int">0</ReturnCode>
<ReturnMessage xsi:type="xsd:string">ok</ReturnMessage>
<Articles xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TArticleInfo[x]">...</Articles>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[0]"/>
</return>
</NS1:GetArticlesInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And this is the Articles array that i need to parse:
<item xsi:type="NS3:TArticleInfo">
<ArticleId xsi:type="xsd:long">5000001716</ArticleId>
<ArticleName xsi:type="xsd:string">Coca Cola</ArticleName>
<ArticleNumber xsi:type="xsd:int">1</ArticleNumber>
<Available xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:long[3]">
<item>5000000210</item>
<item>5000000208</item>
<item>5000000209</item>
</Available>
<DepartmentId xsi:type="xsd:long">5000000170</DepartmentId>
<Prices xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TItemPrice[2]">
<item xsi:type="NS3:TItemPrice">
<ArticleId xsi:type="xsd:long">5000001716</ArticleId>
<PriceId xsi:type="xsd:long">5000000206</PriceId>
<Amount xsi:type="xsd:double">2</Amount>
<Vat xsi:type="xsd:double">21</Vat>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[0]"/>
</item>
<item xsi:type="NS3:TItemPrice">
<ArticleId xsi:type="xsd:long">5000001716</ArticleId>
<PriceId xsi:type="xsd:long">5000000207</PriceId>
<Amount xsi:type="xsd:double">1.7</Amount>
<Vat xsi:type="xsd:double">12</Vat>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[0]"/>
</item>
</Prices>
<FreeOption xsi:type="xsd:long">5000000145</FreeOption>
<Options xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:long[1]">
<item>5000000143</item>
</Options>
<IsMenu xsi:type="xsd:boolean">false</IsMenu>
<IsManualPrice xsi:type="xsd:boolean">false</IsManualPrice>
<IsActive xsi:type="xsd:boolean">true</IsActive>
<Promo xsi:type="xsd:boolean">false</Promo>
<HqId xsi:type="xsd:string">Coca Cola</HqId>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[5]">
<item xsi:type="NS3:TExtraInfo">
<Key xsi:type="xsd:string">daily_stock_active</Key>
<Value xsi:type="xsd:string">0</Value>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[0]"/>
</item>
<item xsi:type="NS3:TExtraInfo">
<Key xsi:type="xsd:string">daily_stock_qty</Key>
<Value xsi:type="xsd:string">0</Value>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[0]"/>
</item>
<item xsi:type="NS3:TExtraInfo">
<Key xsi:type="xsd:string">purchase_price</Key>
<Value xsi:type="xsd:string">0.0000</Value>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[0]"/>
</item>
<item xsi:type="NS3:TExtraInfo">
<Key xsi:type="xsd:string">course_id</Key>
<Value xsi:type="xsd:string">5000001331</Value>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[0]"/>
</item>
<item xsi:type="NS3:TExtraInfo">
<Key xsi:type="xsd:string">info</Key>
<Value xsi:type="xsd:string"/>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[0]"/>
</item>
</Extra>
</item>
Parameter Type Description
ArticleId Long Internal Id of this Article
ArticleName String Name of this Article
ArticleNumber Integer Number of this Article
Available [Long] List of Sales Area Id's where this Article is available
Prices [ItemPrice] List of Prices for this Article
DepartmentId Long Id of the Department where this Article belongs to
FreeOption Long Free Option ID
Options [Long] List of must-have options
IsMenu Boolean Returns true if this Article is a menu
IsManualPrice Boolean Returns true if this Article requires a manual price input when ordered
IsActive Boolean Returns if true is this Article is active
Promo Boolean Return true if this Article is a Cobmo/Promo article
HqId String HQ Id
Extra [ExtraInfo] List of extra fields
List of available extra fields:
Key Description
course_id Only return articles of a specific course
daily_stock_active 1/0 (if DailyStock=1 was specified in request’s Extra fields)
daily_stock_qty Daily stock quantity (if DailyStock=1 was specified in request’s Extra fields)
info Article info (tab 9 of the article settings in back-office)
plu When PLU is not zero
purchase_price Purchase price
ArticleShort
ArticleShort Object
<item xsi:type="NS3:TArticleShort">
<ArticleId xsi:type="xsd:long">5000001716</ArticleId>
<ArticleName xsi:type="xsd:string">Coca Cola</ArticleName>
<ArticleNumber xsi:type="xsd:int">1</ArticleNumber>
<SalesAreaId xsi:type="xsd:long">5000000210</SalesAreaId>
<DepartmentId xsi:type="xsd:long">5000000170</DepartmentId>
<HqId xsi:type="xsd:string">Coca Cola</HqId>
<Extra xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="NS3:TExtraInfo[0]"/>
</item>
How can I parse this soap XML response in php curl to get the Articles array data? I have tried SimpleXMLElement but I am unable to parse this.
I have surfed a lot for answers but not able to get the correct parsing technique. Shall I use Xpaths if yes, then how to create an XPath to parse the articles array?
A simple solution using XPath and SimpleXML, which from the look of the XML doesn't involve namespaces for the XPath itself. This loads the XML and then looks for an element called <return> with a direct descendant called <Articles>. As xpath() returns a list of nodes, it then just picks the first one (using [0]) and iterates of the <item> elements enclosed and outputs the <ArticleId> elements value....
$xml = simplexml_load_string($data);
$articles = $xml->xpath("//return/Articles");
foreach ( $articles[0]->item as $item ) {
echo (string)$item->ArticleId.PHP_EOL;
}
With the test data this gives...
5000001716
5000001716

PHP - Access Item from XML with xpath()

I want to get the ISBN number of a book from an Amazon XML File. I already checked other posts and tried to solve the problem with them but without any success. The $xml looks like:
<itemlookupresponse>
<items>
<item>
<itemattributes>
<studio>Pottermore from J.K. Rowling</studio>
<eisbn>9781781100769</eisbn>
</itemattributes>
</item>
<item>
<itemattributes>
<studio>Carlsen Verlag GmbH</studio>
<isbn>3551551677</isbn>
</itemattributes>
</item>
<item>
<itemattributes>
<studio>Carlsen</studio>
<isbn>3551551677</isbn>
</itemattributes>
</item>
</items>
</itemlookupresponse>
I want to get the items, where the ISBN equals 3551551677. For that reason, I used the following command, which unfortunately returns an empty array.
$item = $xml->xpath('//items/item[itemattributes/isbn=3551551677]');
I would be glad, if someone could help me and explain, what I made wrong.
XML and XPath are case-sensitive. Amazon's XML is not all lowercase, despite what you've posted in your question. Adjust your XPath to match the exact case used in Amazon's actual XML.
Note also that if there are namespaces involved in the actual XML, those too must be accounted for in your XPath. See How does XPath deal with XML namespaces?
You didn't show something important (namespaces?) because this code works for me:
$string = <<<XML
<itemlookupresponse>
<items>
<item>
<itemattributes>
<studio>Pottermore from J.K. Rowling</studio>
<eisbn>9781781100769</eisbn>
</itemattributes>
</item>
<item>
<itemattributes>
<studio>Carlsen Verlag GmbH</studio>
<isbn>3551551677</isbn>
</itemattributes>
</item>
<item>
<itemattributes>
<studio>Carlsen</studio>
<isbn>3551551677</isbn>
</itemattributes>
</item>
</items>
</itemlookupresponse>
XML;
$xml = new SimpleXMLElement($string);
/* Поиск <a><b><c> */
$items = $xml->xpath('//items/item[ ./itemattributes/isbn[.="3551551677"] ]');
//$items = $xml->xpath('//items/item[itemattributes/isbn=3551551677]');
echo "Result size: " . count($items) . "\n";
foreach ( $items as $item) {
echo $item->asXML() . "\n";
}

Incorrect PHP SOAP Formatting

I am trying to make use of the stand soapClient for PHP. I can make a class successfully using SOAP UI however when I trry and make that call using PHP this is the difference.
<arrInputs xsi:type="ns1:KeyValueArrayInput" SOAP-ENC:arrayType="ns1:KeyValueArray[]" >
<item xsi:type="ns1:KeyValueArray">
<Key xsi:type="xsd:string">Realm</Key>
<Value xsi:type="xsd:string">test</Value>
</item>
<item xsi:type="ns1:KeyValueArray">
<Key xsi:type="xsd:string">UserName</Key>
<Value xsi:type="xsd:string">test15</Value>
</item>
Now when I try send it via the php soap client I get this.
<arrInputs SOAP-ENC:arrayType="ns1:KeyValueArray[22]" xsi:type="ns1:KeyValueArrayInput">
<item xsi:type="ns1:KeyValueArray">
<Key xsi:type="xsd:string">Realm</Key>
<Value xsi:type="xsd:string">test</Value>
</item>
<item xsi:type="ns1:KeyValueArray">
<Key xsi:type="xsd:string">UserName</Key>
<Value xsi:type="xsd:string">test2</Value>
</item>
Any suggestions as to how the type and the array type have been switched around. If I put the type in front of the arrayType all is good.
$creationFields = array();
$creationFields['strSessionID'] = $this->getSessionHash();
$arrInputs = array();
foreach ($params as $k => $v)
{
$arrInputs[] = array('Key' => $k, 'Value' => $v);
}
$creationFields['arrInputs'] = $arrInputs;
__soapCall('methodName', $creationFields);
This is out of the WSDL:
<message name="methodName"><part name="strSessionID" type="xsd:string" /><part name="arrInputs" type="tns:KeyValueArrayInput" /></message>

Parse XML Parent node of matching attribute

I have an XML like the one below, I am trying to do an xpath query and parse it with simplexml. The XML is a CURL response and is stored in a $response variable. I need to look the Code attribute inside the <Item> and select the parent <Product> to parse it.
$response:
<Items>
<Product>
<Item Code="123">
</Item>
<Price>170
</Price>
</Product>
<Product>
<Item Code="456">
</Item>
<Price>150
</Price>
</Product>
</Items>
This is what I am doing:
$xml = simplexml_import_dom($response);
function loadNode($code){
global $xml;
$scode = $xml->xpath('//Item[contains(#Code,"' . $code . '")]/..');
echo $scode->Items->Product->Price;
}
loadNode("123");
This is the Notice I get:
Notice: Trying to get property of non-object
A couple of observations:
The xpath() method returns an array of SimpleXMLElement
objects, not a single SimpleXMLElement. (Yes, even though there can only be a single parent of an element, you still have to get it as the first member of the array ([0]).
$scode->Items->Product->Price should be changed to just
$scode->Price.
These modifications to your PHP code:
<?php
$response = <<<XML
<Items>
<Product>
<Item Code="123">
</Item>
<Price>170
</Price>
</Product>
<Product>
<Item Code="456">
</Item>
<Price>150
</Price>
</Product>
</Items>
XML;
$xml = simplexml_load_string($response);
function loadNode($code) {
global $xml;
$scode = $xml->xpath('//Item[contains(#Code,' . $code . ')]/..')[0];
echo $scode->Price;
}
loadNode("123");
?>
When run will yield this output:
170
as expected.

I can't get all the data from an xml file with php

I can get the data from the xml apart from all the <Item> data. The code below only gets the data for the last one. I thought the foreach would get it for each of them but it doesn't seem to.
<magic5Out version="2.1.0">
<Report customerPK="Survey_2" locationPK="229" userId="2299" template="13600" formDate="2012-04-11T00:00:00" dateTimeStarted="2012-04-11T07:34:04" dateTimeMobileReleased="2012-04-11T07:37:03" currentStatus="5" reportGuid="b174d011-77bb-4882-b87e-a2c60bdf265d">
<Results>
<Item itemPK="SurveyTab_9">
<q1 listEntry="1.8m" listEntryId="239107"/>
<q1Comments text=""/>
<q2 listEntry="Green" listEntryId="239113"/>
<q2Comments text=""/>
<item_comments text="test"/>
</Item>
<Item itemPK="SurveyTab_24">
<q1 listEntry="2.2m" listEntryId="239108"/>
<q1Comments text=""/>
<q2 listEntry="Silver" listEntryId="239112"/>
<q2Comments text=""/>
<item_comments text=""/>
</Item>
<Item itemPK="SurveyTab_10">
<q1 listEntry="3.0m" listEntryId="239110"/>
<q1Comments text=""/>
<q2 listEntry="White" listEntryId="239111"/>
<q2Comments text=""/>
<item_comments text="No feed"/>
</Item>
<Item itemPK="SurveyTab_23">
<q1 listEntry="2.2m" listEntryId="239108"/>
<q1Comments text=""/>
<q2 listEntry="Green" listEntryId="239113"/>
<q2Comments text=""/>
<item_comments text=""/>
</Item>
<surveyorComments0 text="testing"/>
<surveyorName text="NICK"/>
<surveyorSig opFile="D:\Sites\WebApp_eden\Output\2100\XMLSurvey\Attachments\1cf582f9-776c-472e-b8ce-877a51fae5e1.png"/>
</Results>
</Report>
</magic5Out>
here's the php I'm using:
$xml = simplexml_load_file($xml_file);
/* more code here that works OK */
foreach($xml->Report->Results->Item as $tab) {
$tab_name = (string) $tab['itemPK'];
$q1_result = $tab->q1['listEntry'];
$q2_result = $tab->q2['listEntry']; etc.
$q1_comment = escape_data($tab->q1Comments['text']);
$q2_comment = escape_data($tab->q2Comments['text']);
$item_comment = escape_data($tab->item_comments['text']);
}
When you make a loop and define a variable then you have in your case the last value from the loop in your variable.
You overwrite your variable everytime.
foreach($xml->Report->Results->Item as $tab) {
$tab_name[] = (string) $tab['itemPK'];
$q1_result[] = $tab->q1['listEntry'];
$q2_result[] = $tab->q2['listEntry']; etc.
$q1_comment[] = escape_data($tab->q1Comments['text']);
$q2_comment[] = escape_data($tab->q2Comments['text']);
$item_comment[] = escape_data($tab->item_comments['text']);
}
try something like this. Then you have an array with all the values.
There must have been something elsewhere in the code that was screwing this up - I tried a load of other things and eventually reverted to the php I posted above and it worked this time. Hope it was only my own time I wasted on this.

Categories