Traversing XML structure in PHP - php

How can I read the state in this object of an array
I am getting this result when I
$xml = simplexml_load_string($xml_string);
display_output($xml->country[0]);
RESULT:
SimpleXMLElement::__set_state(array(
'#attributes' =>
array (
'name' => 'Afghanistan',
),
'state' =>
array (
0 => 'Badakhshan',
1 => 'Badghis',
2 => 'Baghlan',
3 => 'Balkh',
4 => 'Bamian',
5 => 'Farah',
6 => 'Faryab',
7 => 'Ghazni',
8 => 'Ghowr',
9 => 'Helmand',
10 => 'Herat',
11 => 'Jowzjan',
12 => 'Kabol',
13 => 'Kandahar',
14 => 'Kapisa',
15 => 'Konar',
16 => 'Kondoz',
17 => 'Laghman',
18 => 'Lowgar',
19 => 'Nangarhar',
20 => 'Nimruz',
21 => 'Oruzgan',
22 => 'Paktia',
23 => 'Paktika',
24 => 'Parvan',
25 => 'Samangan',
26 => 'Sar-e Pol',
27 => 'Takhar',
28 => 'Vardak',
29 => 'Zabol',
),
))
I would like to get the state, how can I do it? I have tried, unfortunately it is not working.
$a = $xml->country[0]->state[0];
*below is the xml:
<?xml version="1.0" encoding="utf-8"?>
<countries>
<country name="Afghanistan">
<state>Badakhshan</state>
<state>Badghis</state>
<state>Baghlan</state>
<state>Balkh</state>
<state>Zabol</state>
</country>
</countries>
Update, found the answer:
$xml = simplexml_load_string($xml_string);
$country = array();
$state = array();
for($x=0;$x<count($xml);$x++)
{
$country[] = (string)$xml->country[$x]->attributes()->name;
if(isset($xml->country[$x]->state))
{
for($y=0;$y<count($xml->country[$x]->state);$y++)
{
$state[$x][] = (string)$xml->country[$x]->state[$y];
}
}
}
return array($country,$state);

I would think you would use xpath to look for the attribute "Afghanistan" on a country element, since you know this is the country you are looking to get data for.
$afghanistan = $xml->xpath("//country[#name='Afghanistan']");
$afghan_states = $afghanistan->state;
$first_state = $afghan_states[0];
Or if you don't need the country level information, you could use a more specific xpath selector:
$afghan_states = $xml->xpath("//country[#name='Afghanistan']/state");
$first_state = $afghan_states[0];
This would make your code work even if there were changes in country element ordering in the XML.

Related

I want to remove the common elements in two arrays using PHP [duplicate]

This question already has answers here:
How to remove an array value from another array using PHP question
(3 answers)
Closed 2 years ago.
I tried the following code and it should be working, but not getting the required result. What's wrong with the code? I have two arrays and I want to remove the common elements in both arrays so I wore the following code.
<?php
$aMgaMembersList= array (
0 => '9194962',
1 => '9197448',
2 => '9174039',
3 => '9199473',
4 => '9175598',
5 => '9197474',
6 => '9195444',
7 => '9195268',
8 => '9189438',
9 => '9175103',
10 => '9199619',
11 => '9195267',
12 => '9194463',
13 => '9196333',
14 => '9197471',
15 => '9198479',
16 => '9197472',
17 => '9185479',
18 => '9197452',
19 => '9197442',
20 => '9180861',
21 => '9194950',
22 => '9198464',
23 => '9199613',
24 => '9175939',
25 => '9195442',
26 => '9190203',
27 => '9199613',
) ;
$aRocketMembersList = array (
0 => '9174039',
1 => '9175103',
2 => '9175598',
3 => '9175939',
4 => '9180861',
5 => '9185479',
6 => '9189438',
7 => '9190203',
8 => '9194463',
9 => '9194950',
10 => '9194962',
11 => '9195267',
12 => '9195268',
13 => '9195442',
14 => '9195444',
15 => '9196333',
16 => '9197442',
17 => '9197448',
18 => '9197452',
19 => '9197471',
20 => '9197472',
21 => '9197474',
22 => '9198464',
23 => '9198479',
24 => '9199473',
25 => '9199613',
26 => '9199619',
27 => 'arun',
) ;
if (is_array($aRocketMembersList)) {
foreach ($aRocketMembersList as $rocketUsername) {
if (in_array($rocketUsername, $aMgaMembersList)) {
unset($aMgaMembersList[array_search($rocketUsername, $aMgaMembersList)]);
unset($aRocketMembersList[array_search($rocketUsername, $aRocketMembersList)]);
}
}
}
print_r($aRocketMembersList);
print_r($aMgaMembersList);
The out put is
Array
(
[27] => arun
)
Array
(
[27] => 9199613
)
The element 9199613 shouldn't be there. Why it's happening? I ran the code in a different environment and the result is same.
Here's a different function that works regardless of the order of Arrays:
<?php
function different($array1, $array2){
$m = array_merge($array1, $array2); $x = array_intersect($array1, $array2); $a = array_diff($m, $x); $b = array_diff($x, $m); $a = array_merge($a, $b);
$r = [];
foreach($a as $v){
$o = new StdClass; $k = array_search($v, $array1);
if($k === false)$k = array_search($v, $array2);
$o->$k = [$array1[$k], $array2[$k]]; $r[] = $o;
}
return $r;
}
$aMgaMembersList = [
0 => '9194962',
1 => '9197448',
2 => '9174039',
3 => '9199473',
4 => '9175598',
5 => '9197474',
6 => '9195444',
7 => '9195268',
8 => '9189438',
9 => '9175103',
10 => '9199619',
11 => '9195267',
12 => '9194463',
13 => '9196333',
14 => '9197471',
15 => '9198479',
16 => '9197472',
17 => '9185479',
18 => '9197452',
19 => '9197442',
20 => '9180861',
21 => '9194950',
22 => '9198464',
23 => '9199613',
24 => '9175939',
25 => '9195442',
26 => '9190203',
27 => '9199613'
];
$aRocketMembersList = [
0 => '9174039',
1 => '9175103',
2 => '9175598',
3 => '9175939',
4 => '9180861',
5 => '9185479',
6 => '9189438',
7 => '9190203',
8 => '9194463',
9 => '9194950',
10 => '9194962',
11 => '9195267',
12 => '9195268',
13 => '9195442',
14 => '9195444',
15 => '9196333',
16 => '9197442',
17 => '9197448',
18 => '9197452',
19 => '9197471',
20 => '9197472',
21 => '9197474',
22 => '9198464',
23 => '9198479',
24 => '9199473',
25 => '9199613',
26 => '9199619',
27 => 'arun'
];
$diffArray = different($aMgaMembersList, $aRocketMembersList);
$test = json_encode($diffArray);
?>
$tmp1 = array_diff($aMgaMembersList,$aRocketMembersList);
$tmp2 = array_diff($aRocketMembersList,$aMgaMembersList);
$final = array_unqiue(array_merge($tmp1, $tmp2));
unset($tmp1);unset($tmp2);//and maybe original arrays?
There are probably better solutions, but that should work for you. If you had associative arrays instead of numeric values you could exclude array_unqiue
EDIT:
I originally assumed you wanted the results in one array, if that's unnecessary just use the array_diff function twice, and you can maintain your original array names as desired. Again there are probably better solutions (more memory/processor efficient), but in most practical cases this will be fine. If you're working with extremely large data sets... do more research ;)

Array - Select the sub children id's from an array

I have this array built from a function that sorts allowed or valid url slugs and their ids into another array. I can call the current category id by passing the url slug to the category. Now I need to get the children category ids (if any) so i can call the appropriate items from the database for display purpose.
Heres an example of the array:
Array (
[radios] => 1
[radios/motorola] => 2
[radios/motorola/handheld] => 3
[radios/motorola/mobile] => 4
[radios/icom] => 5
[radios/icom/handheld] => 6
[radios/icom/mobile] => 7
[radios/mics-and-speakers] => 8
[radios/mounts] => 9
[radios/radio-other] => 10
[misc] => 11
[misc/led] => 12
[phones] => 13
[phones/samsung] => 14
[phones/lg] => 15
[phones/motorola] => 16
[phones/huawei] => 17
[phones/blackberry] => 18
[phones/flip] => 19
[boosters] => 20
[boosters/standalone] => 21
[boosters/indoor-antenna] => 22
[boosters/outdoor-antenna] => 23
[boosters/connections] => 24
[accessories] => 25
[accessories/cases] => 26
[accessories/other] => 27
[internet] => 28
[internet/fusion] => 29
[internet/point-to-point] => 30
[internet/hotspots] => 31
[internet/gateways] => 32
[internet/switches] => 33
[cameras] => 34
[cameras/complete-kits] => 35
[cameras/additional-cameras] => 36
[cameras/other] => 37
);
As you can see, each result points to the category ID of that group. If i visit the following url:
http://example.com/store/cameras
I can print out that THE PATH CURRENTLY IS: 34 which is correct. Since It has children under it, I also need their ID's and the ID's of any of their children, etc etc. That way on radios, i can show ALL of the sub category items, and on radios/motorola i am only showing the Motorola based items and its children, and such down the line.
If there an easy way, using this array I have now, to sort the children (if any) all the way down and get back just their id's (preferably in a new array) for showing database items?
You might want to create a function like this to filter your array,
function filterArray($array, $term) {
$pattern = "/\b" . str_replace($term, '/', '\/') . "\b/i";
foreach($array as $key => $value) {
if(preg_match($pattern, $key)) {
/* Following condition makes sure that your search
will match starting from the beginning. */
if (stripos(trim($key), $term) === 0){
$filtred[] = $value;
}
}
}
}
Then call the above function with the $array and your search $term.
filterArray($array, 'radios') will give you this,
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 [9] => 10 )
filterArray($array, 'radios/motorola') will give you this,
Array ( [0] => 2 [1] => 3 [2] => 4 )
And so on.. I hope this helps.
You can maybe try double layer array, so that you can store values like this,
Array (
[name] => John
[surname] => Smith
[contact] => Array (
[address] => 18 Maple Street
[number] => 555 477 77 77
)
)
This way if you need to print something from "contact" you can use a loop and print all childs of contact field.

PHP convert formatted string (title + values) to multidimensional array

I would like to convert this formatted string to multidimensional array but I can't manage to do it.
The goal is to extract titles header (Dreg Time, FN, SS_ID, MAC, Sector ID, Type, Reason, CMPNT, Basic, Cid) and associating the corresponding values.
Because in the finality I would need to process the data in the "Reason" column.
String:
$log = ": mss get dereg_log 2 500
---------- MODEM 2 MAC ---------
Dreg Time FN SS_ID MAC Sector ID Type Reason CMPNT Basic Cid
2017/08/29 08:20:39:627 0x4da9f0 8277 00:24:a0:xx:xx:xx 1 2 25 0 86
2017/08/29 07:17:33:478 0x421c02 8238 00:23:a2:xx:xx:xx 1 3 59 0 47
2017/08/29 06:00:43:232 0x340a41 8508 00:23:a2:xx:xx:xx 1 1 6 13 317
Total Deregistrations since sector active in sector 1: 9576
Derigistrations since dreg log last reset in sector 1: 9576
Deregistration Types:
DEREG_MSS_IMMEDIATE = 0
DEREG_MSS_DREG_REQ_FROM_AP = 1
DEREG_MSS_DREG_REQ_FROM_MS = 2
DEREG_MSS_RNG_RSP_ABORT_FROM_AP = 3
DEREG_MSS_CONTACT_LOST = 4
---------------------------------
2017-Aug-29 08:31:53.860";
Desired Array:
Array
(
[0] => Array
(
[Dreg Time] => '2017/08/29 08:20:39:627'
[FN] => '0x4da9f0'
[SS_ID] => '8277'
[MAC] => '00:24:a0:xx:xx:xx'
[Sector ID] => '1'
[Type] => '2'
[Reason] => '25'
[CMPNT] => '0'
[Basic Cid] => '86'
)
[1] => Array
(
[Dreg Time] => '2017/08/29 07:17:33:478'
[FN] => '0x421c02'
[SS_ID] => '8238'
[MAC] => '00:23:a2:xx:xx:xx'
[Sector ID] => '1'
[Type] => '3'
[Reason] => '59'
[CMPNT] => '0'
[Basic Cid] => '47'
)
[2] => Array
(
[Dreg Time] => '2017/08/29 06:00:43:232'
[FN] => '0x340a41'
[SS_ID] => '8508'
[MAC] => '00:23:a2:xx:xx:xx'
[Sector ID] => '1'
[Type] => '1'
[Reason] => '6'
[CMPNT] => '13'
[Basic Cid] => '317'
)
)
Code tried:
echo '<pre>';
// remove blank lines
$log = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $log);
// remove new lines
$log = preg_replace('/^.+\n.+\n/', '', $log);
$lines = explode( "\n\n", $log );
$return = array();
foreach ($lines as $line) {
$items = explode("\n", $line);
$return[array_shift($items)] = $items;
}
print_r($return);
Result:
Array
(
[Dreg Time FN SS_ID MAC Sector ID Type Reason CMPNT Basic Cid] => Array
(
[0] => 2017/08/29 08:20:39:627 0x4da9f0 8277 00:24:a0:xx:xx:xx 1 2 25 0 86
[1] => 2017/08/29 07:17:33:478 0x421c02 8238 00:23:a2:xx:xx:xx 1 3 59 0 47
[2] => 2017/08/29 06:00:43:232 0x340a41 8508 00:23:a2:xx:xx:xx 1 1 6 13 317
[3] => Total Deregistrations since sector active in sector 1: 9576
[4] => Derigistrations since dreg log last reset in sector 1: 9576
[5] => Deregistration Types:
[6] => DEREG_MSS_IMMEDIATE = 0
[7] => DEREG_MSS_DREG_REQ_FROM_AP = 1
[8] => DEREG_MSS_DREG_REQ_FROM_MS = 2
[9] => DEREG_MSS_RNG_RSP_ABORT_FROM_AP = 3
[10] => DEREG_MSS_CONTACT_LOST = 4
[11] => ---------------------------------
[12] => 2017-Aug-29 08:31:53.860
)
)
Your code was an incomplete attempt, and contained a few errors - e.g. you removed newlines from the log, and then tried split the string based on newlines! Then you tried to split a single line by newline, when clearly a single line cannot, by implication, contain a newline. Also the code just naively ran through each line and added it directly to the array rather than creating an associative array within each index, as shown in the desired output. And lastly it did nothing to try and identify which lines actually contained the desired output.
This will do it:
$log = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $log);
$lines = explode( "\n", $log );
$return = array();
foreach ($lines as $line) {
$line = preg_replace("/\s+/", " ", $line); //condense and standardise the whitespace between each item, so that explode can work.
$items = explode(" ", $line);
if (count($items) == 10 && preg_match("/^[0-9]{4}/", $items[0])) //restrict to lines starting with the year, and with the correct number of columns
$return[] = array(
"Dreg Time" => $items[0]." ".$items[1],
"FN" => $items[2],
"SS_ID" => $items[3],
"MAC" => $items[4],
"Sector_ID" => $items[5],
"Type" => $items[6],
"Reason" => $items[7],
"CMPNT" => $items[8],
"Basic_Cid" => $items[9]
);
}
echo "<pre>".var_export($return, true)."</pre>";

PHP: How to store values from a big (bidimensional) array into different arrays in a foreach loop

i have an array in which each key it has another array.
What i want to do is to store those values in different arrays.
For example, the original array looks like the following:
Array
(
[0] => Array
(
[concurso] => 2758
[R1] => 12
[R2] => 20
[R3] => 33
[R4] => 46
[R5] => 50
[R6] => 51
[R7] => 54
)
[1] => Array
(
[concurso] => 2759
[R1] => 12
[R2] => 15
[R3] => 31
[R4] => 50
[R5] => 54
[R6] => 55
[R7] => 11
)
[2] => Array
(
[concurso] => 2760
[R1] => 4
[R2] => 11
[R3] => 12
[R4] => 40
[R5] => 45
[R6] => 51
[R7] => 55
)
.
.
.
[29] => Array
(
[concurso] => 2787
[R1] => 3
[R2] => 5
[R3] => 19
[R4] => 24
[R5] => 28
[R6] => 30
[R7] => 15
)
)
And for each key i want to store the corresponding values in different arrays (where 'concurso' will be the key of each new array and its corresponding Rn value):
R1:
Array
(
[2758] => 12
[2759] => 12
[2760] => 4
...
[2787] => 3
)
R2:
Array
(
[2758] => 20
[2759] => 15
[2760] => 11
...
[2787] => 5
)
R3:
Array
(
[2758] => 33
[2759] => 31
[2760] => 12
...
[2787] => 19
)
R4:
Array
(
[2758] => 46
[2759] => 50
[2760] => 40
...
[2787] => 24
)
R5:
Array
(
[2758] => 50
[2759] => 54
[2760] => 45
...
[2787] => 28
)
R6:
Array
(
[2758] => 51
[2759] => 55
[2760] => 51
...
[2787] => 30
)
...
Rn:
How do i achieve this? I guess i need to create variable names dynamically, since the number of elements of a given array may change depending on the data retrieved.
What do you suggest?
I am trying this code but no luck so far:
$ultimos_sorteos_m,true); //this is the big array shown above
foreach($ultimos_sorteos_m as $key1 => $last_sorteos){
$contador=count($last_sorteos); //how many items the current sub-array has
$k=1; //an index
echo '<p>the number of items is '.$contador.'</p>';
foreach($last_sorteos as $key=>$valor){
if($key=='concurso'){
$concurso=$valor;
echo 'concurso: '.$concurso.' <br>'; //to get the 'concurso' that will work as a key for the other arrays
}
//storing here the rest of the values
if(substr( $key, 0, 1 ) === "R" && substr($key, 1, 1)===$k){
//i don't know here how to store the values in different arrays
echo 'storing value: '.$valor.'<br>';
$Ritems[$concurso]=$valor; //the problem is that only store the last value
}
}
}
If you want to know why, I want it this way in order to graph those data by using the phpgraphlib graphing library. It will be a graph showing different lines.
Try this : This creates variable names dynamically so you dont need to know the number for R1,R2,R3 etc elements you have
<?php
foreach($ultimos_sorteos_m[0] as $key1 => $last_sorteos){
$$key1 = array_column($ultimos_sorteos_m, $key1 , 'concurso'); // This is a dynamic variable name. See http://php.net/manual/en/language.variables.variable.php
}
var_dump($R1);
var_dump($R2);
?>
Please comment if you see a problem. Thanks!
Like this?
foreach($orig_array[0] as $key => $_)
$new_array[$key] = array_column($orig_array, $key, 'concurso');
array_column
shim for php < 5.5
If you're absolutely sure you need R1, R2 as variables (you don't), you can extract() the array afterwards.
You can use array_column. Try this if your PHP version 5.5+
$R1 = array_column($arr, 'R1', 'concurso');
.
.
.
$R7 = array_column($arr, 'R7', 'concurso');

Converting a One-Dimensional Array into a Nested Array Using Relationship Keys

Say I have an array with keys representing id and values representing parent:
4 => 0
2 => 0
5 => 2
6 => 5
8 => 0
9 => 0
10 => 8
12 => 0
13 => 0
14 => 0
18 => 7
19 => 18
20 => 19
21 => 20
22 => 21
23 => 22
24 => 23
28 => 20
7 => 5
You could also read this as an object:
{
id : 4,
parent : 0
} // etc...
The multidimensional array I'd want to achieve from this would be:
4 => 0
2 => 5
=> 6
=> 7
=> 18
=> 19
=> 20
=> 21
=> 22
=> 23
=> 24
=> 28
8 => 10
9 => 0
12 => 0
13 => 0
14 => 0
How would I go about doing this?
If you write a little helper function to rework your data to a structure similar to:
$input = array(
array('id' => '4', 'parent' => '0'),
// ...
);
which could be achieved with something like:
$data = array_map(function ($entry) {
list($id, $parent) = array_map('trim', explode('=>', $entry));
return array(
'id' => $id,
'parent' => $parent
);
}, explode("\n", $data));
you could then use a function I used in a similar question:
function flatToNested($d, $r = 0, $p = 'parent', $k = 'id', $c = 'children') {
$m = array();
foreach ($d as $e) {
isset($m[$e[$p]]) ?: $m[$e[$p]] = array();
isset($m[$e[$k]]) ?: $m[$e[$k]] = array();
$m[$e[$p]][] = array_merge($e, array($c => &$m[$e[$k]]));
}
return $m[$r];
}
to produce a nested array with:
$nested = flatToNested($data);
demo: http://codepad.viper-7.com/HAZxaA

Categories