Achieving same array structure when converting from JSON and XML - php

I'm trying to build my first public API, which is going pretty fine, but i ran into some trouble converting different data formats that will get POSTed. Basically, the API should accept both JSON and XML, and now i'm trying to convert those into a common PHP array structure.
For JSON my example looks like this:
$people = array( array('name' => 'casper',
'shoesize' => 41
),
array('name' => 'christine',
'shoesize' => 37
)
);
$data = json_encode($people);
return json_decode($data);
This will result in:
[{"name":"casper","shoesize":"41"},{"name":"charlotte","activated":"1"}]
The XML example is as follows:
$xml = '<?xml version="1.0"?>'.
'<people>'.
'<person>'.
'<name>casper</name>'.
'<shoesize>41</shoesize>'.
'</person>'.
'<person>'.
'<name>christine</name>'.
'<shoesize>37</name>'.
'</person>'.
'</people>';
$xml = simplexml_load_string($xml);
$data = json_encode($xml);
return json_decode($data);
This will result in:
{"person":[{"name":"casper","shoesize":"42"},{"name":"christina","shoesize":"12"}]}
Can anyone figure out how i will be able to achieve the same array structure in both examples?

i think this could help you :-
$xml = '<?xml version="1.0"?>'.
'<people>'.
'<person>'.
'<name>casper</name>'.
'<shoesize>41</shoesize>'.
'</person>'.
'<person>'.
'<name>christine</name>'.
'<shoesize>37</shoesize>'.
'</person>'.
'</people>';
$xml = simplexml_load_string($xml);
$data = json_encode($xml);
echo '<pre>';
$dataarray=(json_decode($data,true));
$requiredarray=$dataarray['person'];
print_r($requiredarray);
Output :-
Array
(
[0] => Array
(
[name] => casper
[shoesize] => 41
)
[1] => Array
(
[name] => christine
[shoesize] => 37
)
)

Related

Transform array into normal array

My Array looks like this
Array (
[title] => SimpleXMLElement Object (
[0] => Car String
)
)
And should look like this:
Array (
title => Car String
)
I got this array by doing curl_exec a xml file and changed it with "new SimpleXMLElement".
Every solution i could find didn't work.
So how can i transform the array? Or is there a more efficient way to get a xml with http header options?
When you build your array, you need to cast the SimpleXMLElement Object into the desired type. In your case you need to cast into a string element.
There is the simple way to do that :
$xmlString = "<element><title>Car String</title></element>";
$xml = new SimpleXMLElement($string);
$array = [
'title' => (string)$xml->title;
];
or
$xmlString = "<element><title>Car String</title></element>";
$xml = new SimpleXMLElement($string);
$array = [
'title' => $xml->title->__toString();
];

How can I extract value from an xml

I'm new to PHP. I'm trying to get the data out of the below XML. Now, in my code $data->Address contains value of the below code i.e:
$data->Address = "<tolist></tolist>
<cclist>
<cc>
<contactpersonname>niraj</contactpersonname>
<name>niraj</name>
<email>stgh#gmail.com</email>
<number>+91.3212365212</number>
<prefix>Ms.</prefix>
<contactpersonprefix>Ms.</contactpersonprefix>
</cc>
<cc>
<contactpersonname>fdg</contactpersonname>
<name>admin</name>
<email>admin12#gmail.com</email>
<number>+91.4554343234</number>
<prefix>Mr.</prefix>
<contactpersonprefix>Mr.</contactpersonprefix>
</cc>
</cclist>";
Now I want to extract the <contactpersonname> tag and print it. How can I do this?
Since your XML is missing a tag that encompasses all others, you need to create on in order to get parsers to work properly:
<?php
$buffer = "<tolist></tolist>
<cclist>
<cc>
<contactpersonname>niraj</contactpersonname>
<name>niraj</name>
<email>stgh#gmail.com</email>
<number>+91.3212365212</number>
<prefix>Ms.</prefix>
<contactpersonprefix>Ms.</contactpersonprefix>
</cc>
<cc>
<contactpersonname>fdg</contactpersonname>
<name>admin</name>
<email>admin12#gmail.com</email>
<number>+91.4554343234</number>
<prefix>Mr.</prefix>
<contactpersonprefix>Mr.</contactpersonprefix>
</cc>
</cclist>";
// ***** wrap the whole thing in a <root> tag...
$xml = simplexml_load_string("<root>".$buffer."</root>");
$array = json_decode(json_encode((array) $xml), 1);
echo "<pre>";
print_r($array);
echo "</pre>";
?>
Result:
Array
(
[tolist] => Array
(
)
[cclist] => Array
(
[cc] => Array
(
[0] => Array
(
[contactpersonname] => niraj
[name] => niraj
[email] => stgh#gmail.com
[number] => +91.3212365212
[prefix] => Ms.
[contactpersonprefix] => Ms.
)
[1] => Array
(
[contactpersonname] => fdg
[name] => admin
[email] => admin12#gmail.com
[number] => +91.4554343234
[prefix] => Mr.
[contactpersonprefix] => Mr.
)
)
)
)
UPDATED
Now you can navigate down to where you want to go with
echo "<pre>";
$ccList = $array['cclist'];
$cc = $ccList['cc'];
$contacts = array();
foreach($cc as $i=>$val) {
$contacts[$i]=$val['contactpersonname'];
}
echo "first contact: " . $contacts[0] . "<br>";
echo "second contact: " . $contacts[1] ."<br>";
Result:
first contact: niraj
second contact: fdg
You can convert the XML to an array with the following code:
$xml = simplexml_load_string($buffer);
$array = json_decode(json_encode((array) $xml), 1);
Where $buffer is the xml string.
Then you can obtain the person name as follow:
$data->Address = $array['cclist']['cc']['contactpersonname'];
It's a quick and dirty method to convert the xml to an array, but it works.
Try this..
$xml = new SimpleXMLElement($string);
$results = $xml->xpath('cclist/cc/contactpersonname');
http://php.net/manual/en/simplexmlelement.xpath.php
$xml = simplexml_load_file("note.xml");
echo $xml->contactpersonname;
This requires you to load it form an xml file. If you already have the string in the code I'd recommend a regex. If you know the data won't ever be incorrect written!
$pattern = '#<contactpersonname>(.*?)</contactpersonname>#';
echo preg_match ($pattern, $data->Address);

Retrieving specific values from a SoapClient Return in PHP

I call an webservice using PHP 5.3.1 and my request looks as so:
<?php
$client = new SoapClient('the API wsdl');
$param = array(
'LicenseKey' => 'a guid'
);
$result = $client->GetUnreadIncomingMessages($param);
echo "<pre>";
print_r($result);
echo "</pre>";
?>
Here is the response that I get back:
stdClass Object
(
[GetUnreadIncomingMessagesResult] => stdClass Object
(
[SMSIncomingMessage] => Array
(
[0] => stdClass Object
(
[FromPhoneNumber] => the number
[IncomingMessageID] => message ID
[MatchedMessageID] =>
[Message] => Hello there
[ResponseReceiveDate] => 2012-09-20T20:42:14.38
[ToPhoneNumber] => another number
)
[1] => stdClass Object
(
[FromPhoneNumber] => the number
[IncomingMessageID] =>
[MatchedMessageID] =>
[Message] => hello again
[ResponseReceiveDate] => 2012-09-20T20:42:20.69
[ToPhoneNumber] => another number
)
)
)
)
To get to the data you want to retrieve you need to navigate through multiple nested objects. The objects are of stdClass type. It is my understanding that you can access nested objects in a stdClass but I am going to cast them to arrays to make indexing easier.
So start with:
<?php
$client = new SoapClient('the API wsdl');
$param = array('LicenseKey' => 'a guid');
$result = $client->GetUnreadIncomingMessages($param);
You now have a $result vavialble of type stdClass. This has a single object in it also of type stdClass called "GetUnreadIncomingMessagesResult." This Object in turn contains an array called "SMSIncomingMessage." That array contains a varriable number of objects of stdClass that hold the data you want.
So we do the following:
$outterArray = ((array)$result);
$innerArray = ((array)$outterArray['GetUnreadIncomingMessagesResult']);
$dataArray = ((array)$innerArray['SMSIncomingMessage']);
Now we have an array holding each object we want to extract data from. So we loop through this array to get the holding object, cast the holding object to an array and than extract the necessary information. You do this as follows:
foreach($dataArray as $holdingObject)
{
$holdingArray = ((array)$holdingObject);
$phoneNum = $holdingArray['FromPhoneNumber'];
$message = $holdingArray['Message'];
echo"<div>$fphone</div>
<div>$message</div>";
}
?>
This should give you the output you are looking for. You can adjust where you index the holdingArray to get out whatever specific information you are looking for.
The complete code looks like:
<?php
$client = new SoapClient('the API wsdl');
$param = array('LicenseKey' => 'a guid');
$result = $client->GetUnreadIncomingMessages($param);
$outterArray = ((array)$result);
$innerArray = ((array)$outterArray['GetUnreadIncomingMessagesResult']);
$dataArray = ((array)$innerArray['SMSIncomingMessage']);
foreach($dataArray as $holdingObject)
{
$holdingArray = ((array)$holdingObject);
$phoneNum = $holdingArray['FromPhoneNumber'];
$message = $holdingArray['Message'];
echo"<div>$fphone</div>
<div>$message</div>";
}
?>

add to associative array

I have some xml that looks like this:
<?xml version="1.0"?>
<data>
<items>
<item><timestamp>2011-07-11T09:01:42Z</timestamp><title><![CDATA[ some data here ]]></title><link>http://twitter.com/aurl</link></item>
<item><timestamp>2011-05-11T09:01:42Z</timestamp><title><![CDATA[ some data here ]]></title><link>http://twitter.com/aurlhere</link></item>
</items>
and I'm trying to loop over it and add it to an array:
foreach($xml->items->item as $e) {
$feedData['timestamp'] = $e->timestamp;
$feedData['title'] = $e->title;
$feedData['link'] = $e->link;
$feedData['type'] = $e->type;
}
print_r($feedData);
The xml is there and if I put an echo in the foreach I get back 10 responses (whcih are how many items I have) but when I print the array out all I get is one line (which is the last entry in the xml doc).
Array ( [timestamp] => SimpleXMLElement Object ( [0] => 2011-07-08T08:05:19Z ) [title] => SimpleXMLElement Object ( ) [link] => SimpleXMLElement Object ( [0] => http://twitter.com.aurl ) [type] => SimpleXMLElement Object ( ) )
I suspoect I'm overwriting the array on each loop. But why ? It should be adding to the array. Sorry my php isn't great...hence what Is suspect is a bit of a stupid question.
$i = 0;
foreach($xml->items->item as $e) {
$feedData[$i]['timestamp'] = $e->timestamp;
$feedData[$i]['title'] = $e->title;
$feedData[$i]['link'] = $e->link;
$feedData[$i]['type'] = $e->type;
$i++;
}
print_r($feedData);
Well, there is only one $feedData array and you are always setting the value for some specific keys, e.g. $feedData['timestamp']. How do you think this should add to the array? Keys are unique, the same key cannot appear twice, so yes, you are just overwriting the values.
It seems you want an array of arrays:
$feedData = array();
foreach($xml->items->item as $e) {
$feedData[] = array(
'timestamp' => $e->timestamp;
'title' => $e->title;
'link' => $e->link;
'type' => $e->type;
);
}
Have a look at the array manual [docs] for more information about arrays.

SimpleXML and XML collections - how to get the attribute value as an array key?

I'm just trying to figure out how to cleanly and nicely transform a XML collection into an appropriate object. See, I've got this very simple XML string :
$x = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<apiKeys>
<apiKey application="app1">HfxaoMBJJ9pLe</apiKey>
<apiKey application="app2">HfxaoMBJJ9pLeClsSHsh</apiKey>
<apiKey application="app3">HfxaoMBJJ9pLeClsSHshTI9qX</apiKey>
</apiKeys>';
Which I transform using :
$O_xmlElement = simplexml_load_string ($x);
This is what I get :
SimpleXMLElement Object
(
[apiKey] => Array
(
[0] => HfxaoMBJJ9pLe
[1] => HfxaoMBJJ9pLeClsSHsh
[2] => HfxaoMBJJ9pLeClsSHshTI9qX
)
)
And I'd rather have (I expected !) something like :
SimpleXMLElement Object
(
[apiKey] => Array
(
['app1'] => HfxaoMBJJ9pLe
['app2'] => HfxaoMBJJ9pLeClsSHsh
['app3'] => HfxaoMBJJ9pLeClsSHshTI9qX
)
)
Thank you very much for your help people
SimpleXML won't do what you want automatically. You'll have to build the object yourself:
$O_xmlElement = simplexml_load_string($x);
$myObject = new stdClass();
foreach ($O_xmlElement->apiKey as $apiKey) {
$key = (string) $apiKey['application'];
$myObject->${key} = (string) $apiKey;
}
Refer to the basic usage example in the PHP manual for good examples of dealing with child elements and attributes.
When getting attributes from a SimpleXMLElement, remember that each attribute will be a SimpleXMLElement and not a string. You'll want to explicitly cast each attribute to string before using it as an array key or object property name.
Not sure you can do it exactly as you want it, but you can check out php.net's docs here:
http://www.php.net/manual/en/simplexmlelement.attributes.php
Basically the attributes can be found inside an object attached to each of the apiKey objects.
You can use the following code:
$xml = simplexml_load_string($x);
$newArray = array();
$count=0;
foreach($xml as $value){
$key= (string)($xml->apiKey[$count++]->attributes()->application);
$newArray[$key] = $value[0];
}
$newArray = array_map("trim", $newArray);
print_r($newArray);
This will generate the following output:
Array
(
[app1] => HfxaoMBJJ9pLe
[app2] => HfxaoMBJJ9pLeClsSHsh
[app3] => HfxaoMBJJ9pLeClsSHshTI9qX
)

Categories