I'm close to finishing a script which uses simplexml to process some data but I am stuck at the last.
Well, not stuck, but curious and stuck.
$tmp contains my XML (approx 750k) and the goal is to get it into a format for fputcsv (a parent array containing an array for each row).
The below works, but instead of a nice clean array that I can use fputcsv and send back to user there is a lot of overhead which I do not need for writing to a CSV file and which will create me problems no doubt with fputcsv. I have cleaned the output up into just a couple of header columns and just a couple of rows, but in reality there are 20 columns and hundreds of rows. Anyway to clean before fputcsv?
// Process XML response into arrays for fputcsv
$csv = array();
$xml = simplexml_load_string($tmp);
// Create array and loop each column for header row
$header_row = array();
foreach ($xml->RESPONSE->DATA->HEADER->COLUMN as $column) {
$header_row[] = $column;
}
$csv[] = $header_row;
// Create array and loop each column for header row
foreach ($xml->RESPONSE->DATA->ROW as $row) {
$data_row = array();
foreach ($row->COLUMN as $datacolvalue){
$data_row[] = $datacolvalue;
}
$csv[] = $data_row;
unset($data_row);
}
// Output var to check for accuracy (later add fputcsv)
var_dump($csv);
Output (print_r - can var_dump if required):
Array
(
[0] => Array
(
[0] => SimpleXMLElement Object
(
[0] => date
)
[1] => SimpleXMLElement Object
(
[0] => name
)
)
[1] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[data_type] => text
)
[0] => Aug 01, 2011
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[data_type] => text
[id] => 8699636
)
[0] => bfxgbfgxbfbgxfsfsdf
)
)
[2] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[data_type] => text
)
[0] => Aug 01, 2011
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[data_type] => text
[id] => 8699694
)
[0] => bfxgbfgxbfbgxf
)
)
)
Desired output (extrapolated for each additional column and removing #attributes):
array(
array("date","name"),
array("Aug 01, 2011","bfxgbfgxbfbgxfsfsdf"),
array("Aug 01, 2011","bfxgbfgxbfbgxf")
)
Try changing
foreach ($xml->RESPONSE->DATA->HEADER->COLUMN as $column) {
to
$columns = (array)$xml->RESPONSE->DATA->HEADER->COLUMN;
foreach ($columns as $column) {
That should convert the SimpleXML objects to simple arrays. Which should remove the "overhead". Do the same for foreach ($row->COLUMN as $datacolvalue){.
Answering my own question, because I probably didn't explain it well enough, but specifying a (string) got me to where I needed to be.
Related
I start from xml file with following input:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<severa>
<mesaj id="6caca93f" tip="ATENTIONARE"cod="GALBEN"" />
<mesaj id="6caca93g" tip="ATENTIONARE" cod="GALBEN" />
</severa>
Using PHP with xml2Array function I obtain below array:
Array
(
[0] => Array
(
[#attributes] => Array
(
[id] => 6caca93f
[tip] => ATENTIONARE
[cod] => GALBEN
)
)
[1] => Array
(
[#attributes] => Array
(
[id] => 6caca93g
[tip] => ATENTIONARE
[cod] => GALBEN
)
)
)
I read this result with foreach and insert this 2 records into MySql.
Now the problem: this works only for multiple records in xml (>2). If I have only one record in xml the array look like below and no row is inserted. Could you please advice what I should do?
Seems that this array with a single entry have a different form. I hope this is not the reason
Thank you so much!
Array
(
[#attributes] => Array
(
[id] => 6caca93f
[tip] => ATENTIONARE
[cod] => GALBEN
)
)
Foreach is like this:
foreach ($a as $row) {
$atributes = $row['#attributes'];
$id = $atributes['id'];
$tip = $atributes['tip'];
$cod = $atributes['cod'];
mysqli_stmt_execute($st);
}
Your xml2Array function is treating a single record differently from a list of records, adding an extra dimension in the second case. You need to treat the first case specially.
if (isset($a['#attributes'])) { // Single record, turn it into an array
$a = array($a);
}
Then your loop will work for both cases.
I have JSON like this (from nested sorting)
[
{"id":13},{"id":14},
{"id":15,
"children":[
{"id":16},{"id":17},{"id":18}
]
},
{"id":19},{"id":20},
{"id":21,
"children":[
{"id":22}
]
}
]
how I PHP loop to put this JSON in MySQL
Thank you.
As with any valid JSON format string, you can use PHP's built-in json_decode to convert it into a parsable object and then loop through those parameters. In this case, from the JSON string you've given (which seems to be an array)
$array = json_decode($string);
foreach ($array as $val) {
//The object $val will be:
"id":13
}
If it's nested, you would do another foreach loop and detect for the property that needs to be looped. For example you could do this in a variety of ways (check for the "children" property, loop through the $val properties and check if it is an array, if it is then loop through that). Inside this foreach loop iteration, you can insert it, or do execute whatever statement you need to get it inside MySQL
Your question is pretty vague on the format and way you want it inserted. I'd suggest showing some code you've tried so other people can help you and know what direction you're going in. (that's probably the reason for the downvote, not mine by the way)
Looping through all the properties of object php
just put your valid json inside json_decode and assign it to a php array as below
//$php_arr = json_decode('YOUR_JSON');
$php_arr = json_decode('[{"id":13},{"id":14},{"id":15,"children":[{"id":16},{"id":17},{"id":18}]},{"id":19},{"id":20},{"id":21,"children":[{"id":22}]}]');
/*comment the following 3 lines when done*/
echo "<pre>";
print_r($php_arr);
echo "</pre>";
/*comment the above 3 lines when done*/
output
Array
(
[0] => stdClass Object
(
[id] => 13
)
[1] => stdClass Object
(
[id] => 14
)
[2] => stdClass Object
(
[id] => 15
[children] => Array
(
[0] => stdClass Object
(
[id] => 16
)
[1] => stdClass Object
(
[id] => 17
)
[2] => stdClass Object
(
[id] => 18
)
)
)
[3] => stdClass Object
(
[id] => 19
)
[4] => stdClass Object
(
[id] => 20
)
[5] => stdClass Object
(
[id] => 21
[children] => Array
(
[0] => stdClass Object
(
[id] => 22
)
)
)
)
Now as you have PHP array do what ever you want like
foreach($php_arr as $arr){
if(!isset($arr['children'])){
$q = "insert into tbl(id) values('".$arr['id']."')";
}else{
//your logic
}
}
You need to use json_decode function to decode JSON data. Then use foreach loop to manipulate data.
Try example
$str = '
[{"id":13},{"id":14},{"id":15,"children":[{"id":16},{"id":17},{"id":18}]},{"id":19},{"id":20},{"id":21,"children":[{"id":22}]}]
';
$json = json_decode($str);
//var_dump($json);
foreach ($json as $item)
{
//The object $val will be:
echo $item->id."<br />";
//You INSERT query is here
//echo "INSERT INTO table (field) VALUE ($item->id)";
$query = mysqli_query($conn, "INSERT INTO table (field) VALUE ($val->id)");
}
Given a deep array, how do you display line-delimited values from it?
Array (
[0] => Array (
[godzina] => SimpleXMLElement Object (
[0] => 17:00:00
)
[data] => SimpleXMLElement Object (
[0] => 2015-09-02
)
[kurs] => SimpleXMLElement Object (
[0] => 2.03
)
)
)
This is the output I'm expecting:
hours: 17:00:00
date: 2015-09-02
exchange: 2.03
I get this array from an xml, via curl, so the source can't be altered.
Figured Out:
$h = 'godzina';
$hvalue = $zmt[$h];
$d = 'data';
$dvalue = $zmt[$d];
$e = 'kurs';
$evalue = $zmt[$e];
and then echo with [0].
BUT thanks. For foreach loop.
Assuming your array is in a variable $myArr, you should be able to do a simple foreach:
foreach ($myArr[0] as $k => $v) {
echo $k.": ".$v[0]."\n"
}
Note, array_chunk is not my solution (It seems to me).
I have an array of about 150.000 elements
Array
(
[0] => Array
(
[name] => Danilo
[phone] => 33568
)
[1] => Array
(
[name] => Alessandro
[phone] => 392222
)
[2] => Array
(
[name] => Alex
[phone] => 3922
)
[3] => Array
(
[name] => Capa
[phone] => 392
)
)
And so on. I would split this array in several arrays, of (for example) 3.000 elements every one.
I saw array_chunk, but it returns a single array with several subarray.
I need several subarray to store them in a database and elaborate in future.
I'm getting crazy to write a snippet starting from that $temp and divide it into smaller array.
$size_chunks = 1;
$temp = array_chunk($recipients, $size_chunks);
foreach ($temp as $key=>$value)
{
if ($key<$size_chunks)
{
$to_store[] = $temp[$key];
}
//print_r($to_store);
// pseudo sql
// INSERT INTO table (sub_recipient) VALUES ($to_store);
$to_store = array();
}
So, every time that for loop end, reduce temp, store $to_store array and restart for others chunks.
Thank you very much.
PS in my example chunk==1 because starting array is small... ;)
With my example of chunk = 1, I need from starting array this 4 arrays:
Array
(
[0] => Array
(
[name] => Danilo
[phone] => 33568
)
)
Array
(
[0] => Array
(
[name] => Alessandro
[phone] => 39222
)
)
Array
(
[0] => Array
(
[name] => Alex
[phone] => 39222
)
)
Array
(
[0] => Array
(
[name] => Capa
[phone] => 392
)
)
Another explain
1 - With a starting array of 15.000 elements, and chunk of 3.000, I need in output (15.000 / 3.000) = 5 arrays. I will save them in database, so in DB I will have 5 rows (a row for every array).
2 - With a starting array of 4 elements, and chunk of 1, I need in output (4 / 1) = 4 arrays. I will save them in database, so in DB I will have 4 rows (a row for every array).
array_chunks() already does what you want, you just have to save it:
$chunks = array_chunk($array, $size_chunks);
foreach ($chunks as $chunk) {
// save $chunk to your database
}
$recipients = Array(
Array("fdbvfdb","dsacsdcds"),
Array("hrloo","dacdsc"),
Array("dcsdc","adcsd"),
Array("dcsdc","adcsd")
);
$total = count($recipients);//count 150.000 elements
$i=1;
for($i=0;$i<$total;$i++){
$O = array_slice($recipients,$i,1);
print_r($O);
//Your insert/Save code
}
you can use this code there is uses Array_Slice
I'm having some problems getting the array in these objects. When I print_r(), the following code is printed. $message_object is the name of the object.
SimpleXMLElement Object
(
[header] => SimpleXMLElement Object
(
[responsetime] => 2012-12-22T14:10:09+00:00
)
[data] => SimpleXMLElement Object
(
[id] => Array
(
[0] => 65233
[1] => 65234
)
[account] => Array
(
[0] => 20992
[1] => 20992
)
[shortcode] => Array
(
[0] => 3255
[1] => 3255
)
[received] => Array
(
[0] => 2012-12-22T11:04:30+00:00
[1] => 2012-12-22T11:31:08+00:00
)
[from] => Array
(
[0] => 6121843347
[1] => 6121820166
)
[cnt] => Array
(
[0] => 24
[1] => 25
)
[message] => Array
(
[0] => Go tramping wellington 11-30
[1] => Go drinking Matakana 2pm
)
)
)
I'm trying to get the id arrays out of the objects with a foreach:
foreach($message_object->data->id AS $id) {
print_r($id);
}
The following reply is sent:
SimpleXMLElement Object ( [0] => 65233 ) SimpleXMLElement Object ( [0] => 65234 )
How do I get the value of [0] or am I going about this wrong? and is there a way to loop though the results and get the object keys?
I have tried to echo $id[0] but it returns no result.
When you use print_r on a SimpleXMLElement there comes magic in between. So what you see is not actually what is there. It's informative, but just not the same as with normal objects or arrays.
To answer your question how to iterate:
foreach ($message_object->data->id as $id)
{
echo $id, "\n";
}
to answer how to convert those into an array:
$ids = iterator_to_array($message_object->data->id, 0);
As this would still give you the SimpleXMLElements but you might want to have the values you can either cast each of these elements to string on use, e.g.:
echo (string) $ids[1]; # output second id 65234
or convert the whole array into strings:
$ids = array_map('strval', iterator_to_array($message_object->data->id, 0));
or alternatively into integers:
$ids = array_map('intval', iterator_to_array($message_object->data->id, 0));
You can cast the SimpleXMLElement object like so:
foreach ($message_object->data->id AS $id) {
echo (string)$id, PHP_EOL;
echo (int)$id, PHP_EOL; // should work too
// hakre told me that this will work too ;-)
echo $id, PHP_EOL;
}
Or cast the whole thing:
$ids = array_map('intval', $message_object->data->id);
print_r($ids);
Update
Okay, the array_map code just above doesn't really work because it's not strictly an array, you should apply iterator_to_array($message_object->data_id, false) first:
$ids = array_map('intval', iterator_to_array$message_object->data->id, false));
See also: #hakre's answer.
You just need to update your foreach like this:
foreach($message_object->data->id as $key => $value) {
print_r($value);
}