Array values disappear in PHP SoapClient call to Cisco phone system - php

I am attempting to consume a SOAP service provided by our Cisco phone system (documentation), to get the current status of a given set of phones. I have an array of phone names, which I'm trying to pass to the service, however, the values of the array are being eaten somewhere
Array of items like so:
$items = array(
0 => "SEP0004F2E57F8C",
1 => "SEP001111BF8758",
2 => "SEP001320BD485C"
);
Attempting to call the method:
$client = new SoapClient(
"https://x.x.x.x/realtimeservice/services/RisPort?wsdl",
array(
"login" => "admin",
"password"=> "xxxxx",
"trace" => true
)
);
$devices = $client->SelectCmDevice(
"",
array(
"SelectBy" => "Name",
"Status" => "Any",
"SelectedItems" => $items
)
);
When I debug the complete request I get the following:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
mlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://schemas.cisco.com/ast/soap/"
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:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:SelectCmDevice>
<StateInfo xsi:type="xsd:string"></StateInfo>
<CmSelectionCriteria xsi:type="ns1:CmSelectionCriteria">
<MaxReturnedDevices xsi:nil="true"/>
<Class xsi:nil="true"/>
<Model xsi:nil="true"/>
<Status xsi:type="xsd:string">Any</Status>
<NodeName xsi:nil="true"/>
<SelectBy xsi:type="xsd:string">Name</SelectBy>
<SelectItems SOAP-ENC:arrayType="ns1:SelectItem[3]" xsi:type="ns1:SelectItems">
<item xsi:type="ns1:SelectItem"/>
<item xsi:type="ns1:SelectItem"/>
<item xsi:type="ns1:SelectItem"/>
</SelectItems>
</CmSelectionCriteria>
</ns1:SelectCmDevice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The correct number of <Item> elements were counted and inserted into the <SelectItems> object, however, the actual item names themselves are gone. I would guess it needs to be <Item>SEP0004F2E57F8C</Item>, etc., but I can't seem to figure out how to make it do that.
Thank you in advance for any help!!!

After searching and trying for several hours I've solved it.
$array['SelectBy'] = "Name";
$array['Status'] = "Any";
$array['SelectItems']['SelectItem[0]']['Item'] = "SEP0015F9B16122";
$array['SelectItems']['SelectItem[1]']['Item'] = "SEP0015F9B16123";
$devices = $client->SelectCmDevice(
"",
$array
);
Just to remember: Status of unknown wouldn't show up in the result.

It might be that the API is expecting different values for the array. The fact that the correct number of items are included is promising.
Is there a way in their API to create a list of selected items one item at a time? i.e. start selecting the items, enter each item that you would like, then end selecting the items? I am not sure that it is understanding the Array argument on the Cisco side. Also, have you tried to manually generate the query in the form you are creating (i.e. if you copy this query, insert your IDs where you are trying to get them) does it work?
Jacob

On further inspection, Cisco's API wants the items in a really weird format anyway, so I am have switched to just creating the full request XML by hand rather than relying on SoapClient to build it for me. Not as nice and clean, but it gets the job done.

Related

PHP - parsing xml which has namespace elements

I read other posts and solutions, and they don't work for me - or perhaps I'm not understanding them well enough.
I have a hp network scanner, and have a perl script that interacts through a series of transactions such that I can initiate a scan. I'm working to port that rather directly to php; more suitable for the server I want to run it on. Some transactions work, some don't. This is about one that doesn't.
I took the XML from one of the queries and it won't successfully parse (or this is where I don't understand it well enough). I'm running php version 7.1.12, in case there is something related to that.
my test outputs this:
> php xmltest.php
SimpleXMLElement Object
(
)
object(SimpleXMLElement)#1 (0) {
}
>
And if the xml is simpler (no name-space info I think), then the print_r() is quite verbose.
And here is the full test script with some actual data to process
error_reporting( E_ALL );
ini_set('display_errors', 1);
$test_1 = <<<EOM
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wst="http://schemas.xmlsoap.org/ws/2004/09/transfer"
xmlns:mex="http://schemas.xmlsoap.org/ws/2004/09/mex"
xmlns:wsdp="http://schemas.xmlsoap.org/ws/2006/02/devprof"
xmlns:PNPX="http://schemas.microsoft.com/windows/pnpx/2005/10"
xmlns:UNS1="http://www.microsoft.com/windows/test/testdevice/11/2005"
xmlns:dd="http://www.hp.com/schemas/imaging/con/dictionaries/1.0"
xmlns:wprt="http://schemas.microsoft.com/windows/2006/08/wdp/print"
xmlns:wscn="http://schemas.microsoft.com/windows/2006/08/wdp/scan">
<SOAP-ENV:Header>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse</wsa:Action>
<wsa:MessageID>urn:uuid:fec6e42d-5356-1f69-9c3a-001f2927cf33</wsa:MessageID>
<wsa:RelatesTo>urn:uuid:704ccde5-6861-415d-bd65-31dd9d7a8b98</wsa:RelatesTo>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<mex:Metadata>
<mex:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2006/02/devprof/ThisDevice">
<wsdp:ThisDevice>
<wsdp:FriendlyName xml:lang="en">Printer (HP Color LaserJet CM1312nfi MFP)</wsdp:FriendlyName>
<wsdp:FirmwareVersion>20140625</wsdp:FirmwareVersion>
<wsdp:SerialNumber>CNB885H665</wsdp:SerialNumber>
</wsdp:ThisDevice>
</mex:MetadataSection>
<mex:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2006/02/devprof/ThisModel">
<wsdp:ThisModel>
<wsdp:Manufacturer xml:lang="en">HP</wsdp:Manufacturer>
<wsdp:ManufacturerUrl>http://www.hp.com/</wsdp:ManufacturerUrl>
<wsdp:ModelName xml:lang="en">HP Color LaserJet CM1312nfi MFP</wsdp:ModelName>
<wsdp:ModelNumber>CM1312nfi MFP</wsdp:ModelNumber>
<wsdp:PresentationUrl>http://192.168.1.20:80/</wsdp:PresentationUrl>
<PNPX:DeviceCategory>Printers</PNPX:DeviceCategory>
</wsdp:ThisModel>
</mex:MetadataSection>
<mex:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2006/02/devprof/Relationship">
<wsdp:Relationship Type="http://schemas.xmlsoap.org/ws/2006/02/devprof/host">
<wsdp:Hosted>
<wsa:EndpointReference>
<wsa:Address>http://192.168.1.20:3910/</wsa:Address>
<wsa:ReferenceProperties>
<UNS1:ServiceIdentifier>uri:prn</UNS1:ServiceIdentifier>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
<wsdp:Types>wprt:PrinterServiceType</wsdp:Types>
<wsdp:ServiceId>uri:1cd4F16e-7c8a-a7a0-3797-00145a8827ce</wsdp:ServiceId>
<PNPX:CompatibleId>http://schemas.microsoft.com/windows/2006/08/wdp/print/PrinterServiceType</PNPX:CompatibleId>
</wsdp:Hosted>
</wsdp:Relationship>
</mex:MetadataSection>
</mex:Metadata>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
EOM;
$myxml1 = simplexml_load_string($test_1);
print_r($myxml1);
var_dump($myxml1);
exit;
?>
There are several parameters nestled in there that I want to pull out. One, for instance is:
<wsa:Address>http://192.168.1.20:3910/</wsa:Address>
Can you help me close my knowledge gap on how to access this parameter?
thanks!
First of all, soap and namespaces just make parsing XML harder than it has to be. I've never parsed XML that had namespaces that actually made the XML better to understand, or had any benefit at all. I fully get why namespaces exist, but it just means jumping through some extra hoops to get the data out. The trick with namespaces is that you have to "enter in" to the namespace branch by asking that the namespace as a child.
<?php
error_reporting( E_ALL );
ini_set('display_errors', 1);
$str = <<<EOM
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wst="http://schemas.xmlsoap.org/ws/2004/09/transfer"
xmlns:mex="http://schemas.xmlsoap.org/ws/2004/09/mex"
xmlns:wsdp="http://schemas.xmlsoap.org/ws/2006/02/devprof"
xmlns:PNPX="http://schemas.microsoft.com/windows/pnpx/2005/10"
xmlns:UNS1="http://www.microsoft.com/windows/test/testdevice/11/2005"
xmlns:dd="http://www.hp.com/schemas/imaging/con/dictionaries/1.0"
xmlns:wprt="http://schemas.microsoft.com/windows/2006/08/wdp/print"
xmlns:wscn="http://schemas.microsoft.com/windows/2006/08/wdp/scan">
<SOAP-ENV:Header>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse</wsa:Action>
<wsa:MessageID>urn:uuid:fec6e42d-5356-1f69-9c3a-001f2927cf33</wsa:MessageID>
<wsa:RelatesTo>urn:uuid:704ccde5-6861-415d-bd65-31dd9d7a8b98</wsa:RelatesTo>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<mex:Metadata>
<mex:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2006/02/devprof/ThisDevice">
<wsdp:ThisDevice>
<wsdp:FriendlyName xml:lang="en">Printer (HP Color LaserJet CM1312nfi MFP)</wsdp:FriendlyName>
<wsdp:FirmwareVersion>20140625</wsdp:FirmwareVersion>
<wsdp:SerialNumber>CNB885H665</wsdp:SerialNumber>
</wsdp:ThisDevice>
</mex:MetadataSection>
<mex:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2006/02/devprof/ThisModel">
<wsdp:ThisModel>
<wsdp:Manufacturer xml:lang="en">HP</wsdp:Manufacturer>
<wsdp:ManufacturerUrl>http://www.hp.com/</wsdp:ManufacturerUrl>
<wsdp:ModelName xml:lang="en">HP Color LaserJet CM1312nfi MFP</wsdp:ModelName>
<wsdp:ModelNumber>CM1312nfi MFP</wsdp:ModelNumber>
<wsdp:PresentationUrl>http://192.168.1.20:80/</wsdp:PresentationUrl>
<PNPX:DeviceCategory>Printers</PNPX:DeviceCategory>
</wsdp:ThisModel>
</mex:MetadataSection>
<mex:MetadataSection Dialect="http://schemas.xmlsoap.org/ws/2006/02/devprof/Relationship">
<wsdp:Relationship Type="http://schemas.xmlsoap.org/ws/2006/02/devprof/host">
<wsdp:Hosted>
<wsa:EndpointReference>
<wsa:Address>http://192.168.1.20:3910/</wsa:Address>
<wsa:ReferenceProperties>
<UNS1:ServiceIdentifier>uri:prn</UNS1:ServiceIdentifier>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
<wsdp:Types>wprt:PrinterServiceType</wsdp:Types>
<wsdp:ServiceId>uri:1cd4F16e-7c8a-a7a0-3797-00145a8827ce</wsdp:ServiceId>
<PNPX:CompatibleId>http://schemas.microsoft.com/windows/2006/08/wdp/print/PrinterServiceType</PNPX:CompatibleId>
</wsdp:Hosted>
</wsdp:Relationship>
</mex:MetadataSection>
</mex:Metadata>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
EOM;
$xml = simplexml_load_string($str);
$namespaces = $xml->getNamespaces(true);
// Here we are saying that we want the Body node in the SOAP-ENV namespace
$body = $xml->children( $namespaces['SOAP-ENV'] )->Body;
// Inside that Body node, we want to get into the mex namespace
$mex = $body->children( $namespaces['mex'] );
// We want the MetadataSections that are in each of the mex namespaces
$metadataSections = $mex->Metadata->MetadataSection;
// Loop through each of the MetadataSections
foreach( $metadataSections as $meta )
{
// Get inside the wsdp namespace
$wsdp = $meta->children( $namespaces['wsdp'] );
// Check if there is a Hosted node inside a Relationship node
if( isset( $wsdp->Relationship->Hosted ) )
{
// Get the wsa namespace inside the Hosted node
$wsa = $wsdp->Relationship->Hosted->children( $namespaces['wsa'] );
// If there is an Address inside the EndpointReference node
if( isset( $wsa->EndpointReference->Address ) )
{
// Then output it
echo $wsa->EndpointReference->Address;
}
}
}
As an extremely simple example - if you just wanted the wsa:Address element...
$myxml1 = simplexml_load_string($test_1);
$myxml1->registerXPathNamespace("wsa", "http://schemas.xmlsoap.org/ws/2004/08/addressing");
echo "wsa:Address=".(string)$myxml1->xpath("//wsa:Address")[0];
This just makes sure that the wsa namespace is registered with the document and available to XPath expressions. Then the XPath expression just says - fetch element wsa:Address from anywhere in the document. But as xpath returns a list of all matches (even if there is only 1) so use [0] to get the first item. This outputs...
wsa:Address=http://192.168.1.20:3910/
If you needed more data around the (for example) <wsdp:Hosted> element, you could do something like...
$myxml1 = simplexml_load_string($test_1);
$myxml1->registerXPathNamespace("wsdp", "http://schemas.xmlsoap.org/ws/2006/02/devprof");
$hosted = $myxml1->xpath("//wsdp:Hosted")[0];
$hostedWSA = $hosted->children("wsa", true);
echo "wsa:Address=".(string)$hostedWSA->EndpointReference->Address.PHP_EOL;
$hostedWSPD = $hosted->children("wsdp", true);
echo "wsdp:Types=".(string)$hostedWSPD->Types.PHP_EOL;
So instead this starts of by fetching the correct element and then working with the various child nodes in the different namespaces within that node.

How to work with SOAP web service and it's XML in php

I want to call a function of a web service in my project developed by PHP. This is my code:
$wsdl="http://x.x.x.x:8090/charge/services/Amount?wsdl";
$client = new SoapClient($wsdl) or die("Error");
$chargeAmountArray = array('UserIdentifier' => $number ,
'data' => array(
'description' => array("Channel=test|".$Origin),
'currency' => NULL,
'code' => $code),
'refrence' => $refcode);
$header = new SoapHeader('servicekey', $servicekey);
$client->__setSoapHeaders($header);
$res = $client->__call('chargeAmount',$chargeAmountArray);
return $res->return;
I have seen my xml code with tcpdump and it is like:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.csapi.org/schema/parlayx/payment/amount_charging/v4_0/local" xmlns:ns2="servicekey">
<SOAP-ENV:Header>
<ns2:e0ce5ed56d7c4d60/>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:chargeAmount/>
<param1>
<item>
<key>description</key>
<value>yChannel=test|30733</value>
</item>
<item>
<key>currency</key>
<value/>
</item>
<item>
<key>code</key>
<value>MOBDY</value>
</item>
</param1>
<param2>1PN1mROoZop2hAy</param2>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
As you see the UserIdentifier is not passed and the refrence parameter has no name in the XML.
I see a few errors here.
The constructor signature for the SoapHeader class shows the first parameter is a namespace declaration, which it doesn't appear you are setting.
Also, SoapClient::__call() is deprecated; instead you should call the method directly:
$res = $client->chargeAmount($chargeAmountArray);
SoapClient::__call() expects parameters in an array with key "parameters", which you are not providing.
Finally, you should be doing some error checking with try/catch in case the connection can't be made for whatever reason.

Zend SOAP: Change the default array element name "item" to class name of complex type in WSDL

this question might be asked, but it is so hard to search for, I just can not find anything about it. Plus it is not easy to ask.
I'm using Zend SOAP's autodiscover to re-create our old SOAP interface (because of switching to micro services and re-working everything).
So far it's working like a charm. But I have one problem in recreating the SOAP response of some services when using lists/arrays.
The old response XML of a SOAP request looked like this. It contains two <SMSEntry>s in the <SMSEntries> list.
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<ns1:getSMSByTimeSpanResult>
<AmountOfEntries>2</AmountOfEntries>
<SMSEntries>
<SMSEntry></SMSEntry>
<SMSEntry></SMSEntry>
</SMSEntries>
</ns1:getSMSByTimeSpanResult>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
But the recreated response looks like this. It contains two <item>s of type SMSEntry in the <SMSentries> list.
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<ns1:getSMSByTimeSpanResponse>
<return xsi:type="ns1:getSMSByTimeSpanResponse">
<AmountOfEntries xsi:type="xsd:int">2</AmountOfEntries>
<SMSEntries SOAP-ENC:arrayType="ns1:SMSEntry[2]" xsi:type="ns1:ArrayOfSMSEntry">
<item xsi:type="ns1:SMSEntry"></item>
<item xsi:type="ns1:SMSEntry"></item>
</SMSEntries>
<DataEx xsi:nil="true"/>
</return>
</ns1:getSMSByTimeSpanResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I have no control of the clients. They might be checking for a SMSEntry with comparing the string. I want to use the class name SMSEntry for the XML-tag name.
Second, I would like to leave out the additional, wrapping everything, <return> tag.
I am using the autodiscover like this:
use Zend\Soap\AutoDiscover;
use Zend\Soap\Wsdl\ComplexTypeStrategy\ArrayOfTypeComplex;
$autoDiscover = new AutoDiscover(new ArrayOfTypeComplex());
$autoDiscover->setClass(new Standard($sm));
The getSMSByTimeSpanResponse is defined like this:
Standard.php
/**
* Class getSMSByTimeSpanResponse
*
* #package LgxServiceManager\Service
*/
class getSMSByTimeSpanResponse
{
/**
* #var int
*/
public $AmountOfEntries;
/**
* #var \LgxServiceManager\Service\SMSEntry[]
*/
public $SMSEntries;
}
/**
* Class SMSEntry
*
* #package LgxServiceManager\Service
*/
class SMSEntry
{
}
Does anybody have any idea on how to this?
I found some code in the library\Zend\Soap\Wsdl\ComplexTypeStrategy\ArrayOfTypeSequence.php:122
Where the _addSequenceType() method is setting an attribute hardcoded:
$element->setAttribute('name', 'item');
But this is in type "Sequence" not type "Complex" like I'm using...
Thank you in advance,
Philipp
\EDIT
oh man... I just discovered another structure which I don't know how to create with Zend SOAP's autodiscover...
<mainMember1>SERIALNUMBER</mainMember1>
<mainMember2>NAMEOFPRODUCT</mainMember2>
<mainMember3>000000-000-0</mainMember3>
<Rules>
<RuleEntry>
<singleValue>allow</singleValue>
<ResourceList>
<Name>generic</Name>
<ResourceEntry>[...]</ResourceEntry>
<ResourceEntry>[...]</ResourceEntry>
<ResourceEntry>[...]</ResourceEntry>
</ResourceList>
<ResourceList>
<Name>default</Name>
<ResourceEntry>[...]</ResourceEntry>
<ResourceEntry>[...]</ResourceEntry>
<ResourceEntry>[...]</ResourceEntry>
</ResourceList>
</RuleEntry>
</Rules>
As you can see, there is a <singleValue> inside the <RuleEntry> but multiple <ResourceList>s. The same structure is used inside the resource lists: One <Name> and multiple <ResourceEntry>...
Is this even possible to handle with autodiscover?
I know this is an old thread, but I am trying to help followers that have the same problem I was facing.
Nowadays we use Laminas, but the principle is the same.
another way to solve the original problem is to do a little change to the
vendor\Laminas\Laminas-Soap\src\Wsdl\ComplexTypeStrategy\ArrayOfTypeSequence.php:124
with a code like this:
// Paulo
// $element->setAttribute('name', 'item'); // Original Code
$element->setAttribute('name', substr($childType, 4));
// Paulo End
Hope this helps everyone
For anyone still having above problem:
Default response of stdClass() like this:
$array = ['lets', 'test', 'it'];
$response = new stdClass();
$response->results = $array;
Will be like:
<return xsi:type="SOAP-ENC:Struct">
<results SOAP-ENC:arrayType="xsd:string[3]" xsi:type="SOAP-ENC:Array">
<item xsi:type="xsd:string">lets</item>
<item xsi:type="xsd:string">test</item>
<item xsi:type="xsd:string">it</item>
</results>
</return>
What we can do - we can change array to ArrayObject():
$array = ['lets', 'test', 'it'];
$response = new stdClass();
$response->results = new ArrayObject();
foreach($array as $item) {
$response->results->append($item);
}
which return:
<return xsi:type="SOAP-ENC:Struct">
<results xsi:type="SOAP-ENC:Struct">
<BOGUS xsi:type="xsd:string">lets</BOGUS>
<BOGUS xsi:type="xsd:string">test</BOGUS>
<BOGUS xsi:type="xsd:string">it</BOGUS>
</results>
</return>
And finally the icing on the cake:
$array = ['lets', 'test', 'it'];
$response = new stdClass();
$response->results = new ArrayObject();
foreach($array as $item) {
$soapVar = new SoapVar($item,XSD_STRING,NULL,NULL,'result');
$response->results->append($soapVar);
}
It will return:
<return xsi:type="SOAP-ENC:Struct">
<results xsi:type="SOAP-ENC:Struct">
<result xsi:type="xsd:string">lets</result>
<result xsi:type="xsd:string">test</result>
<result xsi:type="xsd:string">it</result>
</results>
</return>
As you can see the fifth argument tells what will be the key of xml element. You need to be aware of second argument too, becaouse it tells which is the type of variable. You can find more here:
https://secure.php.net/manual/en/class.soapvar.php

Simplexml element will not store to PHP variable

I am writing a test script in php. I get back XML from the server in simplexml objects. Ive been parsing most fine, some using foreach loops and some directly from the elements. This one response just will not let me store the value to a PHP variable.
This is the specific response
<xml>
<status>1</status>
<count>1</count>
<device id="72220">
<udid>99000146864366</udid>
<devicename>Sprint Wwe</devicename>
<created>2014-07-01 13:22:27</created>
</device>
</xml>
Here is my parsing block
$cRes = $proxy->queryXML($section, 'retrieve', array("device_id" => "all"));
if($cRes->status == '1'){
$dvcID = $cRes->device[0]['id']->__toString();
$devicename = $cRes->device[0]->devicename->__toString();
if(empty($dvcID)) return $do;//
if(empty($devicename)) return $do2;//hacked break points
$res = array("deviceid" => $dvcID,
"devicename" => $devicename);
return $res;
}
The objective is to pull only id and devicename from the first device in an arbitrary amount of devices listed in the response. The php variables seem to not be empty as they dont return on my hacked break points(using notepad++). Ive tried casting them as (string) but they still show up with no data but do not fail the empty() test. Casting the id as an int turns it into a 0. What am I missing here?
The error response from the server is as follows
Last Query:Array
(
[device_id] =>
[devicename] =>
[return_type] => xml
[section] => devices
[action] => update
[api_key] => xxxxxxxxxxxxxxxxxx
)
Last Response<?xml version="1.0" encoding="utf-8"?>
<xml>
<status>0</status>
<error code="410">Required device POST variables not supplied</error>
</xml>

XML to array, xml2ary bug

I am using this function http://mysrc.blogspot.it/2007/02/php-xml-to-array-and-backwards.html
to parse an XML to an Array. Very great function. But the strange thing is that
if I have the following 2 xml files:
<response>
<company prop1=1>
</company>
<company prop1=2>
</company>
</response>
<response>
<company prop1=1>
</company>
</response>
I got different result. For the first case, I got an array of two elements:
Array(
int(0) => _a => Array(...)
int(1) => _a => Array(...)
)
but for the second case I got
Array (
_a => Array(...)
)
which is not an array with indexes as the first case. This complicates parsing.
Does anybody have any idea how to modify the code?
Regards.
Let's say you do something like
$result = xml2ary($xml);
Try adding this line after your call to xml2ary():
$result = is_int(reset(array_keys($result))) ? $result : array($result);
This checks if the first key of the result array is an integer (which means that the xml2ary function returned multiple results. If not, it automatically wraps the $result variable in an array(), so that you have the same response format even when only one XML item is parsed.
Try using the PHP simplexml class:
http://php.net/manual/en/book.simplexml.php
It's the best way to parse XML with PHP

Categories