I have something like this:
$url = "http://ws.geonames.org/findNearbyPostalCodes?country=pl&placename=";
$url .= rawurlencode($city[$i]);
$xml = simplexml_load_file($url);
echo $url."\n";
$cityCode[] = array(
'city' => $city[$i],
'lat' => $xml->code[0]->lat,
'lng' => $xml->code[0]->lng
);
It's supposed to download XML from geonames. If I do print_r($xml) I get :
SimpleXMLElement Object
(
[code] => Array
(
[0] => SimpleXMLElement Object
(
[postalcode] => 01-935
[name] => Warszawa
[countryCode] => PL
[lat] => 52.25
[lng] => 21.0
[adminCode1] => SimpleXMLElement Object
(
)
[adminName1] => Mazowieckie
[adminCode2] => SimpleXMLElement Object
(
)
[adminName2] => Warszawa
[adminCode3] => SimpleXMLElement Object
(
)
[adminName3] => SimpleXMLElement Object
(
)
[distance] => 0.0
)
I do as you can see $xml->code[0]->lat and it returns an object. How can i get the value?
You have to cast simpleXML Object to a string.
$value = (string) $xml->code[0]->lat;
You can also use the magic method __toString()
$xml->code[0]->lat->__toString()
If you know that the value of the XML element is a float number (latitude, longitude, distance), you can use (float)
$value = (float) $xml->code[0]->lat;
Also, (int) for integer number:
$value = (int) $xml->code[0]->distance;
if you don't know the value of XML Element, you can use
$value = (string) $xml->code[0]->lat;
if (ctype_digit($value)) {
// the value is probably an integer because consists only of digits
}
It works when you need to determine if value is a number, because (string) will always return string and is_int($value) returns false
Quick Solution if you in hurry.
convert a Xml-Object to an array (or object),
function loadXml2Array($file,$array=true){
$xml = simplexml_load_file($file);
$json_string = json_encode($xml);
return json_decode($json_string, $array);
}
This is the function that has always helped me convert the xml related values to array
function _xml2array ( $xmlObject, $out = array () ){
foreach ( (array) $xmlObject as $index => $node )
$out[$index] = ( is_object ( $node ) ) ? _xml2array ( $node ) : $node;
return $out;
}
you can use the '{}' to access you property, and then you can do as you wish.
Save it or display the content.
$varName = $xml->{'key'};
From your example her's the code
$filePath = __DIR__ . 'Your path ';
$fileName = 'YourFilename.xml';
if (file_exists($filePath . $fileName)) {
$xml = simplexml_load_file($filePath . $fileName);
$mainNode = $xml->{'code'};
$cityArray = array();
foreach ($mainNode as $key => $data) {
$cityArray[..] = $mainNode[$key]['cityCode'];
....
}
}
try current($xml->code[0]->lat)
it returns element under current pointer of array, which is 0, so you will get value
header("Content-Type: text/html; charset=utf8");
$url = simplexml_load_file("http://URI.com");
foreach ($url->PRODUCT as $product) {
foreach($urun->attributes() as $k => $v) {
echo $k." : ".$v.' <br />';
}
echo '<hr/>';
}
you can convert array with this function
function xml2array($xml){
$arr = array();
foreach ($xml->children() as $r)
{
$t = array();
if(count($r->children()) == 0)
{
$arr[$r->getName()] = strval($r);
}
else
{
$arr[$r->getName()][] = xml2array($r);
}
}
return $arr;
}
$codeZero = null;
foreach ($xml->code->children() as $child) {
$codeZero = $child;
}
$lat = null;
foreach ($codeZero->children() as $child) {
if (isset($child->lat)) {
$lat = $child->lat;
}
}
foreach($xml->code as $vals )
{
unset($geonames);
$vals=(array)$vals;
foreach($vals as $key => $value)
{
$value=(array)$value;
$geonames[$key]=$value[0];
}
}
print_r($geonames);
Related
I have something like this:
$url = "http://ws.geonames.org/findNearbyPostalCodes?country=pl&placename=";
$url .= rawurlencode($city[$i]);
$xml = simplexml_load_file($url);
echo $url."\n";
$cityCode[] = array(
'city' => $city[$i],
'lat' => $xml->code[0]->lat,
'lng' => $xml->code[0]->lng
);
It's supposed to download XML from geonames. If I do print_r($xml) I get :
SimpleXMLElement Object
(
[code] => Array
(
[0] => SimpleXMLElement Object
(
[postalcode] => 01-935
[name] => Warszawa
[countryCode] => PL
[lat] => 52.25
[lng] => 21.0
[adminCode1] => SimpleXMLElement Object
(
)
[adminName1] => Mazowieckie
[adminCode2] => SimpleXMLElement Object
(
)
[adminName2] => Warszawa
[adminCode3] => SimpleXMLElement Object
(
)
[adminName3] => SimpleXMLElement Object
(
)
[distance] => 0.0
)
I do as you can see $xml->code[0]->lat and it returns an object. How can i get the value?
You have to cast simpleXML Object to a string.
$value = (string) $xml->code[0]->lat;
You can also use the magic method __toString()
$xml->code[0]->lat->__toString()
If you know that the value of the XML element is a float number (latitude, longitude, distance), you can use (float)
$value = (float) $xml->code[0]->lat;
Also, (int) for integer number:
$value = (int) $xml->code[0]->distance;
if you don't know the value of XML Element, you can use
$value = (string) $xml->code[0]->lat;
if (ctype_digit($value)) {
// the value is probably an integer because consists only of digits
}
It works when you need to determine if value is a number, because (string) will always return string and is_int($value) returns false
Quick Solution if you in hurry.
convert a Xml-Object to an array (or object),
function loadXml2Array($file,$array=true){
$xml = simplexml_load_file($file);
$json_string = json_encode($xml);
return json_decode($json_string, $array);
}
This is the function that has always helped me convert the xml related values to array
function _xml2array ( $xmlObject, $out = array () ){
foreach ( (array) $xmlObject as $index => $node )
$out[$index] = ( is_object ( $node ) ) ? _xml2array ( $node ) : $node;
return $out;
}
you can use the '{}' to access you property, and then you can do as you wish.
Save it or display the content.
$varName = $xml->{'key'};
From your example her's the code
$filePath = __DIR__ . 'Your path ';
$fileName = 'YourFilename.xml';
if (file_exists($filePath . $fileName)) {
$xml = simplexml_load_file($filePath . $fileName);
$mainNode = $xml->{'code'};
$cityArray = array();
foreach ($mainNode as $key => $data) {
$cityArray[..] = $mainNode[$key]['cityCode'];
....
}
}
try current($xml->code[0]->lat)
it returns element under current pointer of array, which is 0, so you will get value
header("Content-Type: text/html; charset=utf8");
$url = simplexml_load_file("http://URI.com");
foreach ($url->PRODUCT as $product) {
foreach($urun->attributes() as $k => $v) {
echo $k." : ".$v.' <br />';
}
echo '<hr/>';
}
you can convert array with this function
function xml2array($xml){
$arr = array();
foreach ($xml->children() as $r)
{
$t = array();
if(count($r->children()) == 0)
{
$arr[$r->getName()] = strval($r);
}
else
{
$arr[$r->getName()][] = xml2array($r);
}
}
return $arr;
}
$codeZero = null;
foreach ($xml->code->children() as $child) {
$codeZero = $child;
}
$lat = null;
foreach ($codeZero->children() as $child) {
if (isset($child->lat)) {
$lat = $child->lat;
}
}
foreach($xml->code as $vals )
{
unset($geonames);
$vals=(array)$vals;
foreach($vals as $key => $value)
{
$value=(array)$value;
$geonames[$key]=$value[0];
}
}
print_r($geonames);
I'm trying to get 1 value from my XML Array.
This is the code:
<?php
function objectsIntoArray($arrObjData, $arrSkipIndices = array())
{
$arrData = array();
// if input is object, convert into array
if (is_object($arrObjData)) {
$arrObjData = get_object_vars($arrObjData);
}
if (is_array($arrObjData)) {
foreach ($arrObjData as $index => $value) {
if (is_object($value) || is_array($value)) {
$value = objectsIntoArray($value, $arrSkipIndices); // recursive call
}
if (in_array($index, $arrSkipIndices)) {
continue;
}
$arrData[$index] = $value;
}
}
return $arrData;
}
?>
Result:
<?php
$xmlUrl = "http://radiourl:port/status.xsl"; // XML feed file/URL
$xmlStr = file_get_contents($xmlUrl);
$xmlObj = simplexml_load_string($xmlStr);
$arrXml = objectsIntoArray($xmlObj);
print_r($arrXml);
?>
The result of print_r($arrXml); is this:
Array (
[Mount-Point] => /listen.mp3
[Stream-Title] => VibboStream
[Stream-Description] => name
[Content-Type] => audio/mpeg
[Mount-started] => 14/Jun/2016:04:28:49 -0500
[Bitrate] => 128
[Current-Listeners] => 1
[Peak-Listeners] => 3
[Stream-Genre] => Various
[Stream-URL] => http://url [ice-bitrate] => 128
[icy-info] => ice-samplerate=44100;ice-bitrate=128;ice-channels=2
[Current-Song] => Artist - Title
)
So what I'm trying to get is the part [Current-Song] => Artist - Title.
When I echo it I'd like to only see Artist - Title
Can someone help me with this?
You already have the xml object. Just use it.
$artistTitle = $xmlObj->{'Current-Song'};
And just use it from there.
More info on that curly brace syntax here
This is my array format:
$data=["error.png","invoice_1.pdf","invoice2.png"];
But I want to this format:
$data=[{"file":"error.png"},{"file":"invoice_1.pdf"},{"file":"invoice2.png"}]
Thank you.
You should create a new array.
And loop through your existing array.
Its every element will be an array with a value from your array as value.
And key as the string file.
$arr = array();
foreach ($data as $elem) {
$arr[] = array('file' => $elem);
}
Try debugging if you get the correct array:
echo '<pre>';
print_r($arr);
echo '</pre>';
Lastly,
echo json_encode($arr);
exit;
Hope it works for you.
Use
$data = array_map(
function ($item) {
return array('file' => $item);
},
$data
);
to embed the values into arrays, or
$data = array_map(
function ($item) {
$x = new stdClass();
$x->file = $item;
return $x;
},
$data
);
to embed them into objects.
Or, better, use your own class instead of stdClass() and pass $item as argument to its constructor
$data = array_map(
function ($item) {
return new MyClass($item);
},
$data
);
$data = ["error.png", "invoice_1.pdf", "invoice2.png"];
$newarray = array();
foreach ($data as $val){
array_push($newarray, array("file" => $val));
}
print_r($newarray); //Array ( [0] => Array ( [file] => error.png ) [1] => Array ( [file] => invoice_1.pdf ) [2] => Array ( [file] => invoice2.png ) )
echo json_encode($newarray); // [{"file":"error.png"},{"file":"invoice_1.pdf"},{"file":"invoice2.png"}]
exit;
Just try this logic
$data = '["error.png","invoice_1.pdf","invoice2.png"]';
$data = json_decode($data);
$data = array_filter($data, function(&$item){return ($item = array('file' => $item));});
$data = json_encode($data);
I have a multidimensional array like this one in PHP:
Array
(
[folder1] => Array
(
[folder11] => Array
(
[0] => index.html
[1] => tester.html
)
[folder12] => Array
(
[folder21] => Array
(
[0] => astonmartindbs.jpg
)
)
)
)
and should be converted to a "file path" string like this one:
Array
(
[0] => 'folder1/folder11/index.html'
[1] => 'folder1/folder11/tester.html'
[2] => 'folder1/folder12/folder21/astonmartindbs.jpg'
)
Has anybody any ideas?
I have tried a lot any all deleted... This is the starting point of my last try:
public function processArray( $_array ) {
foreach( $_array AS $key => $value ) {
if( is_int( $key ) ) {
} else {
if( is_array( $value ) ) {
$this->processArray( $value );
} else {
}
}
}
echo $this->string;
}
But i do not come to an end.... Hope somebody can help?
A recursive function may be what you are searching for. The following function will work:
/**
* Flattens the array from the question
*
* #param array $a Array or sub array of directory tree
* #param string $prefix Path prefix of $a
*/
function flatten($a, $prefix = './') {
$paths = array();
foreach($a as $index => $item) {
// if item is a string then it is a file name (or a leaf in tree)
// prefix it and add it to paths
if(is_string($item)) {
$paths []= $prefix . $item;
} else {
// if item is a directory we call flatten on it again.
// also we append the new folder name to $prefix
foreach(flatten($item, $prefix . $index . '/') as $path) {
$paths []= $path;
}
}
}
return $paths;
}
var_dump(flatten($a));
Note that flatten() call itself inside the foreach loop with a sub array as argument. This is called a 'recursive algorithm'.
If you like the SPL you can use RecursiveArrayIterator and RecursiveIteratorIterator to iterate over a flat structure.
My result would look like this:
$arr = array(); // your array
$arr = new RecursiveArrayIterator($arr);
$iterator = new RecursiveIteratorIterator($arr, RecursiveIteratorIterator::SELF_FIRST);
$currentDepth = 0;
$currentPath = array();
$result = array();
foreach($iterator as $key => $value) {
// if depth is decreased
if ($iterator->getDepth() < $currentDepth) {
// pop out path values
do {
$currentDepth--;
array_pop($currentPath);
} while($iterator->getDepth() < $currentDepth);
}
if (is_array($value)) {
// add parent to the path
$currentPath[] = $key;
$currentDepth++;
} else {
// add children to result array
$result[] = implode('/', $currentPath).'/'.$value;
}
}
Dumping the data would then look like this:
print_r($result);
/*
Array
(
[0] => folder1/folder11/index.html
[1] => folder1/folder11/tester.html
[2] => folder1/folder12/folder21/astonmartindbs.jpg
)
*/
In your case, you need to implement, a recursive function, that you tried to do, here is a simple code, it may help you,
i am not sure if that is working or no:
$result = array();
$d = 0;
$tmp = "";
public function processArray( $_array ,$before) {
foreach( $_array AS $key => $value ) {
if( is_int( $key ) ) { // If the key is a number, then there is no a sub-array
$result[$d] = $before . '/' . $value;
$d++;
$before="";
} else {
if( is_array( $value ) ) { // if the value is an array, then we will add the key into string that we will return and search into subarray.
$before = $before . '/' . $key;
$this->processArray( $value,$before );
} else {
}
}
}
return $result;
}
Suppose I have an array in PHP that looks like this
array
(
array(0)
(
array(0)
(
.
.
.
)
.
.
array(10)
(
..
)
)
.
.
.
array(n)
(
array(0)
(
)
)
)
And I need all the leaf elements of this mulit-dimensional array into a linear array, how should I go about doing this without resorting recursion, such like this?
function getChild($element)
{
foreach($element as $e)
{
if (is_array($e)
{
getChild($e);
}
}
}
Note: code snippet above, horribly incompleted
Update: example of array
Array
(
[0] => Array
(
[0] => Array
(
[0] => Seller Object
(
[credits:private] => 5000000
[balance:private] => 4998970
[queueid:private] => 0
[sellerid:private] => 2
[dateTime:private] => 2009-07-25 17:53:10
)
)
)
...snipped.
[2] => Array
(
[0] => Array
(
[0] => Seller Object
(
[credits:private] => 10000000
[balance:private] => 9997940
[queueid:private] => 135
[sellerid:private] => 234
[dateTime:private] => 2009-07-14 23:36:00
)
)
....snipped....
)
)
Actually, there is a single function that will do the trick, check the manual page at: http://php.net/manual/en/function.array-walk-recursive.php
Quick snippet adapted from the page:
$data = array('test' => array('deeper' => array('last' => 'foo'), 'bar'), 'baz');
var_dump($data);
function printValue($value, $key, $userData)
{
//echo "$value\n";
$userData[] = $value;
}
$result = new ArrayObject();
array_walk_recursive($data, 'printValue', $result);
var_dump($result);
You could use iterators, for example:
$result = array();
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::LEAVES_ONLY) as $value) {
$result[] = $value;
}
Use a stack:
<?php
$data = array(array(array("foo"),"bar"),"baz");
$results = array();
$process = $data;
while (count($process) > 0) {
$current = array_pop($process);
if (is_array($current)) {
// Using a loop for clarity. You could use array_merge() here.
foreach ($current as $item) {
// As an optimization you could add "flat" items directly to the results array here.
array_push($process, $item);
}
} else {
array_push($results, $current);
}
}
print_r($results);
Output:
Array
(
[0] => baz
[1] => bar
[2] => foo
)
This should be more memory efficient than the recursive approach. Despite the fact that we do a lot of array manipulation here, PHP has copy-on-write semantics so the actual zvals of the real data won't be duplicated in memory.
Try this:
function getLeafs($element) {
$leafs = array();
foreach ($element as $e) {
if (is_array($e)) {
$leafs = array_merge($leafs, getLeafs($e));
} else {
$leafs[] = $e;
}
}
return $leafs;
}
Edit Apparently you don’t want a recursive solution. So here’s an iterative solution that uses a stack:
function getLeafs($element) {
$stack = array($element);
$leafs = array();
while ($item = array_pop($stack)) {
while ($e = array_shift($item)) {
if (is_array($e)) {
array_push($stack, array($item));
array_push($stack, $e);
break;
} else {
$leafs[] = $e;
}
}
}
return $leafs;
}
Just got the same issue and used another method that was not mentioned. The accepted answer require the ArrayObject class to work properly. It can be done with the array primitive and the use keyword in the anonymous function (PHP >= 5.3):
<?php
$data = array(
array(1,2,3,4,5),
array(6,7,8,9,0),
);
$result = array();
array_walk_recursive($data, function($v) use (&$result) { # by reference
$result[] = $v;
});
var_dump($result);
There is no flatten function to get directly the leafs. You have to use recursion to check for each array if has more array children and only when you get to the bottom to move the element to a result flat array.