Simplexml element will not store to PHP variable - php

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>

Related

Parse xml from Ruby script within php failing with StartTag: invalid element name </Envelope>

I have a Ruby script which does a query to a .NET ASP server and gets the result as a string of XML;
<?xml version="1.0" encoding="utf-8"?>
<Envelope>
<Body>
<QueryServicesResponse>
<QueryServicesResult>
<Date>2016-01-01</Date>
<serviceList>
<service>
<uuid>10264b70-87ee-11e6-ae22-56b6b6499611</uuid>
<flight>EZY0000</flight>
<originName>London Heathrow</originName>
<originShort>LHR</originShort>
<destinationName>London Stansted</destinationName>
<destinationShort>STN</destinationShort>
<scheduledDeparture>2016-01-01T14:00:00</scheduledDeparture>
<scheduledArrival>2016-01-01T14:30:00</scheduledArrival>
</service>
</serviceList>
</QueryServicesResult>
</QueryServicesResponse>
</Body>
</Envelope>
This is the section of the ruby scrip which deals with the returned body;
# Post the request
resp, data = http.post(path, data, headers)
# Output the results
doc = Nokogiri::XML(resp.body)
doc.remove_namespaces!
puts doc
The ruby script is called via a php file with the following code;
<?php
$xml = exec("ruby test.rb EZY0000",($results));
$xmlparse = simplexml_load_string($xml);
echo $xmlparse;
?>
But php Throws the following errors when trying to parse the result;
PHP Warning: simplexml_load_string(): Entity: line 1: parser error :
StartTag: invalid element name
PHP Warning: simplexml_load_string(): </Envelope>
I'm trying to parse the xml into a SimpleXMLElement Object I've been trying all sorts of things over the past few days but am stuck or blind to the problem now. I've tried htmlspecialchars but that didn't help either.
The only thing I can think of is this has something to do with the string coming from the ruby script even though it appears to be, and validates as proper xml.
If I take the xml above and use the following php code then everything works as expected and I get the desired result;
<?php
$string = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<Envelope>
<Body>
<QueryServicesResponse>
<QueryServicesResult>
<Date>2016-01-01</Date>
<serviceList>
<service>
<uuid>10264b70-87ee-11e6-ae22-56b6b6499611</uuid>
<flight>EZY0000</flight>
<originName>London Heathrow</originName>
<originShort>LHR</originShort>
<destinationName>London Stansted</destinationName>
<destinationShort>STN</destinationShort>
<scheduledDeparture>2016-01-01T14:00:00</scheduledDeparture>
<scheduledArrival>2016-01-01T14:30:00</scheduledArrival>
</service>
</serviceList>
</QueryServicesResult>
</QueryServicesResponse>
</Body>
</Envelope>
XML;
$xml = simplexml_load_string($string);
print_r($xml);
?>
Which gives me;
SimpleXMLElement Object
(
[Body] => SimpleXMLElement Object
(
[QueryServicesResponse] => SimpleXMLElement Object
(
[QueryServicesResult] => SimpleXMLElement Object
(
[Date] => 2016-01-01
[serviceList] => SimpleXMLElement Object
(
[service] => SimpleXMLElement Object
(
[uuid] => 10264b70-87ee-11e6-ae22-56b6b6499611
[flight] => EZY0000
[originName] => London Heathrow
[originShort] => LHR
[destinationName] => London Stansted
[destinationShort] => STN
[scheduledDeparture] => 2016-01-01T14:00:00
[scheduledArrival] => 2016-01-01T14:30:00
)
)
)
)
)
)
So how can I get the xml from my ruby script into a valid object which I can manipulate in php? Someome offline said I should try and do it all in Rails - but I'm not ready for anything like that much of a challenge at the moment.
So with a hint from #slowjack2k I re-looked at the Ruby file which generates the response.
doc = Nokogiri::XML(resp.body) Which I changed to become doc = Nokogiri::HTML(resp.body) and low and behold it now works and returns a valid xml object in php as expected.

How to get name of very first tag of XML with php's SimpleXML?

I am parsing XML strings using simplexml_load_string(), but I noticed that i don't get the name of the very first tag.
For example, I have these two xml strings:
$s = '<?xml version="1.0" encoding="UTF-8"?>
<ParentTypeABC>
<chidren1>
<children2>1000</children2>
</chidren1>
</ParentTypeABC>
';
$t = '<?xml version="1.0" encoding="UTF-8"?>
<ParentTypeDEF>
<chidren1>
<children2>1000</children2>
</chidren1>
</ParentTypeDEF>
';
NOTICE that they are nearly identical, the only difference being that one has the first node as <ParentTypeABC> and the other as <ParentTypeDEF>
then I just convert them to SimpleXML objects:
$o = simplexml_load_string($s);
$p = simplexml_load_string($t);
but then i have two equal objects, none of them having the "top" node's name appearing, either ParentTypeABC or ParentTypeDEF (I examine the objects using print_r()):
// with top node "ParentTypeABC"
SimpleXMLElement Object
(
[chidren1] => SimpleXMLElement Object
(
[children2] => 1000
)
)
// with top node "ParentTypeDEF"
SimpleXMLElement Object
(
[chidren1] => SimpleXMLElement Object
(
[children2] => 1000
)
)
So how I am supposed to know the top node's name? If I parse unknown XMLs and I need to know what's the top node name, what can I do?
Is there an option in simplexml_load_string() I could use?
I know there are MANY ways to parse XML's with PHP, but I'd like it to be as simple as posible, and to get a simple object or array I could navigate easily.
I made a simple example here to fiddle with.
SimpleXML has a getName() method.
echo $xml->getName();
This should return the name of the respective node, no matter if root or not.
http://php.net/manual/en/simplexmlelement.getname.php

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

Reading a XML File in PHP

I am importing a XML file that has an amount field <amount>$10.00</amount> but when it is read in using code I got from your other posts, the value is returned as .00.
Using:
$xml = simplexml_load_file("testInput.xml");
print_r($xml);
Result:
[amount] => .00
I can't find anywhere why this is failing... Unless it has to do with the $ or period in the value field but I can't find anything about reserved characters.
I tried to duplicate your results and couldn't...
I created a file called xml_test.php:
<?php
$xml = simplexml_load_file('test_input.xml');
print_r($xml);
?>
Then built the XML (test_input.xml):
<?xml version="1.0" encoding="UTF-8"?>
<tests>
<test>
<amount>$10.00</amount>
</test>
</tests>
And this was my result in the browser:
SimpleXMLElement Object ( [test] => SimpleXMLElement Object ( [amount] => $10.00 ) )
Is there anything else going on or am I missing something? Maybe you can paste in your XML...

Array values disappear in PHP SoapClient call to Cisco phone system

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.

Categories