PHP - Simple XML attributes problem - php

I use PHP and Simple XML.
I use a loop that does not work like expected:
foreach($item->Image->attributes()->source as $key => $value)
{
echo $value;
}
In the foreach I try to tell that I want to get the "source" of the image which is listed in the attributes.
$item above is created with a loop around my code above foreach($xml_content->Section->Item as $item {}, (if you need to know where it came from)
My object looks like this:
object(SimpleXMLElement)#36 (4) {
["Text"]=>
string(15) "Vinbergs socken"
["Description"]=>
string(73) "Vinbergs socken ingick i Faurås härad och ligger i Falkenbergs kommun.
"
["Url"]=>
string(44) "http://sv.wikipedia.org/wiki/Vinbergs_socken"
["Image"]=>
object(SimpleXMLElement)#38 (1) {
["#attributes"]=>
array(3) {
["source"]=>
string(113) "http://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Faur%C3%A5s_Vinberg.svg/50px-Faur%C3%A5s_Vinberg.svg.png"
["width"]=>
string(2) "50"
["height"]=>
string(2) "41"
}
}
}
What is wrong with my loop in the beginning of my post?

Your are trying to iterate a string, not an array
$item->Image->attributes()->source
To iterate all the attributes of the Image element, use
foreach ($item->Image->attributes() as $attributeName => $attributeValue) {
If you just want to output the value of the source attribute, do not iterate but use the shorthand
echo $item->Image['source']
See this demo and the SimpleXml Basic Usage Examples in the PHP Manual

Related

PHP Multidimensional Array Extract Specific Values Based Upon Key

I'm trying to create an anchor link by extracting specific array values based upon based upon the key. I've tried using a foreach loop inside of a for loop, however that doesn't seem to work.
Based upon the below multidimensional array how can I loop through each subarray to create individual anchor links, such as:
Example:
/* Array Example */
array(3) {
[0]=>
array(2) {
["#attributes"]=>
array(1) {
["id"] => string(1) "2"
}
["name"]=> string(10) "Mark"
}
[1]=>
array(2) {
["#attributes"]=>
array(1) {
["id"]=> string(1) "4"
}
["name"]=> string(8) "John"
}
[2]=>
array(2) {
["#attributes"]=>
array(1) {
["id"]=> string(1) "5"
}
["name"]=> string(10) "Suzy"
}
/* Desired Output */
Mark
John
Suzy
Let's assume the array you posted is the content of a variable called $users. You can walk through it by doing
foreach ($users as $usr)
{
$usr['#attributes']['id'];
$usr['name'];
}
This way, you can go through every node without worrying about the indexes.
You may output the link on each foreach iteration in several ways. A complete example (which allows to use HTML without escaping every special character) could be:
<?php
foreach ($users as $usr)
{ ?>
<?php echo $usr['name']; ?>
<?php } ?>
While it looks complex, with a lot of PHP opening and closing tags, it makes it easier on the markup with almost no performance penalty
You can use either ways: ($array is your array)
$names = array_column($array, 'name');
$ids = array_map(function($ele){return $ele['#attributes']['id'];}, $array);

SimpleXMLElement get non-attribute values

I have the following SimpleXMLElement:
object(SimpleXMLElement)#10 (3) {
["#attributes"]=> array(3) {
["id"]=> string(8) "18022352"
["name"]=> string(14) "The Salmon Man"
["slug"]=> string(14) "the-salmon-man"
}
["bids"]=> object(SimpleXMLElement)#11 (1) {
["price"]=> array(1) {
[0]=> object(SimpleXMLElement)#13 (1) {
["#attributes"]=> array(4) {
["decimal"]=> string(4) "9.60"
["percent"]=> string(5) "10.42"
["backers_stake"]=> string(5) "40.36"
["liability"]=> string(6) "347.00"
}
}
}
}
["offers"]=> object(SimpleXMLElement)#12 (1) {
["price"]=> array(1) {
[0]=> object(SimpleXMLElement)#15 (1) {
["#attributes"]=> array(4) {
["decimal"]=> string(4) "9.20"
["percent"]=> string(5) "10.87"
["backers_stake"]=> string(5) "85.35"
["liability"]=> string(5) "10.41"
}
}
}
}
}
Why does this work:
$horse[0]['name']
but this doesn't:
$horse[0]['bids'] // also tried $horse['bids'] and other ways
I can get the values like below but I was hoping to search the smaller object:
$xml->xpath("//odds/event[#id='$matchid']/market[#slug='to-win']/contract[#name='$pony']/bids"); // $pony == $horse[0]['name']
It's often easier to look at the XML itself, rather than a print_r of the SimpleXML object. In this case, you have something like this:
<horse id="18022352" name="The Salmon Man" slug="the-salmon-man">
<bids>
<price decimal="9.60" percent="10.42" backers_stake="40.36" liability="347.00" />
</bids>
<offers>
<price decimal="9.60" percent="10.42" backers_stake="40.36" liability="347.00" />
</offers>
</horse>
The bids item is an element, and as discussed in the SimpleXML Basic Usage guide, you access child elements with ->foo notation, whereas attributes use ['foo'] notation.
So if $horse is that <horse> element, you need:
$name = $horse['name'];
$bids = $horse->bids;
Note that this is equivalent to explicitly asking for the first child called bids; both forms will work regardless of whether there is actually more than one identically name element:
$bids = $horse->bids[0];
Now there are presumably one or more <price> elements in practice, so you might want to loop over, and then echo each decimal attribute. That would look like this:
foreach ( $horse->bids->price as $price ) {
echo $price['decimal'];
}
Again, this loop will work fine with only one <price>, it will just just loop once. If there is only ever one price, or you only care about the first one, you could just write:
echo $horse->bids->price['decimal'];
Which is equivalent to:
echo $horse->bids[0]->price[0]['decimal'];
Or of course either of these:
echo $horse->bids[0]->price['decimal'];
echo $horse->bids->price[0]['decimal'];
The number of different ways of getting to the same place is one reason I don't recommend relying too much on print_r output. Another is that it sometimes can't display everything that's in the XML, which doesn't mean that data isn't available if you ask for it.

Foreach through an array with objects and return the values and keys

array(14) {
[0]=>
object(stdClass)#2 (2) {
["set_id"]=>
int(44)
["name"]=>
string(7) "Cameras"
}
[1]=>
object(stdClass)#3 (2) {
["set_id"]=>
int(38)
["name"]=>
string(11) "Cell Phones"
}
[2]=>
object(stdClass)#4 (2) {
["set_id"]=>
int(39)
["name"]=>
string(8) "Computer"
}
The Above is my Data.
I want to return the object names ["Set_ID"] etc and the value.
I have googled and googled and tried examples from here with various failures and now I'm giving up.
I have tried to simply manually return data - ie
foreach($result as $results2)
{
foreach($results2->name as $item)
{
echo "<pre>";
print_r($item);
echo "</pre>";
}
}
I have tried all sorts of flavors of it I had kind of hoped the above would at least return data and it didn't - just errored.
In the end, I'd like to be able to both pull names and data. I don't want to have to manually find element names and code it as $result->SET_ID or whatever - I want to be able to just feed SET_ID in as a variable. I think my problem lies with it being an array of objects and I cant access that object name and all..
Im a noob, so any kind of like detailed explanation wouldn't hurt my feelings so I can learn something.
Instead of foreach($results2->name as $item) use foreach($results2 as $item). $results2->name is not an array thus causing the error.
You can read about object iteration in PHP here
foreach($result as $results2)
{
echo $results2->name.' '.$results2->set_id;
}

Modify data in php codeigniter active record result without changing structure

I've got a codeigniter active record query that uses get('table_name')->result();
The output is below, what i'd like to do is unserialize(base_64_decode) the "venue_opening_hours" string and replace that string in the data structure with the result of the unserialized & base64_decoded data. I know i can array_walk to do this normally, but i don't see how to access that particular bit of data as an object within an array...
Thanks!
array(2) {
[0]=>
object(stdClass)#142 (4) {
["entry_id"]=>
string(2) "15"
["google-id"]=>
string(40) "552e7c08d3b86c14d130ebe43a0ba421d03a60ae"
["venue_opening_hours"]=>
string(148) "YToxOntzOjEzOiJvcGVuaW5nX2hvdXJzIjthOjE6e3M6NzoicGVyaW9kcyI7YToxOntzOjQ6Im9wZW4iO2E6Mjp7czozOiJkYXkiO3M6MToiNSI7czo0OiJ0aW1lIjtzOjQ6IjIzMTUiO319fX0="
["title"]=>
string(18) "Place Name"
}
[1]=>
object(stdClass)#143 (4) {
["entry_id"]=>
string(2) "18"
["google-id"]=>
string(40) "71d9c8e1f64f330637c96d30a0ae15533836a85e"
["venue_opening_hours"]=>
string(972) "YToxOntzOjEzOiJvcGVuaW5nX2hvdXJzIjthOjE6e3M6NzoicGVyaW9kcyI7YToxMDp7aTowO2E6MTp7czo1OiJjbG9zZSI7YToyOntzOjM6ImRheSI7czoxOiIxIjtzOjQ6InRpbWUiO3M6NDoiMjMzMCI7fX1pOjE7YToxOntzOjQ6Im9wZW4iO2E6Mjp7czozOiJkYXkiO3M6MToiMSI7czo0OiJ0aW1lIjtzOjQ6IjIzMTUiO319aToyO2E6MTp7czo1OiJjbG9zZSI7YToyOntzOjM6ImRheSI7czoxOiIxIjtzOjQ6InRpbWUiO3M6NDoiMjMxNSI7fX1pOjM7YToxOntzOjQ6Im9wZW4iO2E6Mjp7czozOiJkYXkiO3M6MToiMSI7czo0OiJ0aW1lIjtzOjQ6IjIzMzAiO319aTo0O2E6MTp7czo1OiJjbG9zZSI7YToyOntzOjM6ImRheSI7czoxOiIyIjtzOjQ6InRpbWUiO3M6NDoiMjMxNSI7fX1pOjU7YToxOntzOjQ6Im9wZW4iO2E6Mjp7czozOiJkYXkiO3M6MToiMiI7czo0OiJ0aW1lIjtzOjQ6IjIzMzAiO319aTo2O2E6MTp7czo1OiJjbG9zZSI7YToyOntzOjM6ImRheSI7czoxOiI0IjtzOjQ6InRpbWUiO3M6NDoiMjMzMCI7fX1pOjc7YToxOntzOjQ6Im9wZW4iO2E6Mjp7czozOiJkYXkiO3M6MToiNCI7czo0OiJ0aW1lIjtzOjQ6IjIzMzAiO319aTo4O2E6MTp7czo1OiJjbG9zZSI7YToyOntzOjM6ImRheSI7czoxOiI1IjtzOjQ6InRpbWUiO3M6NDoiMjM0NSI7fX1pOjk7YToxOntzOjQ6Im9wZW4iO2E6Mjp7czozOiJkYXkiO3M6MToiNSI7czo0OiJ0aW1lIjtzOjQ6IjIzNDUiO319fX19"
["title"]=>
string(24) "Other place name"
}
}
You'd access it using:
$array[0]->venue_opening_hours
in a for loop...
//foreach ($array as &$arrayItem)
//{
foreach ($arrayItem as &$object)
{
// extract and convert it...
//$openinghours = unserialize(base64_decode($object->venue_opening_hours));
// Update it...
$object->venue_opening_hours = $unserialize(base64_decode($object->venue_opening_hours));
}
//}
The &$object is a reference, so the assignment will change the value in the original result set...
Also I forgot to also loop the array ... I think! so added the outer loop :)

A list of arrays contained in a master array PHP

I hope I can make this question clear enough.
I'm looking to put a list of arrays inside one master array, dynamically, so that it looks like this:
masterarray {
array1
{ [0]=>VAL1 [1]=>VAL2 }
array2
{ [0]=>VAL1 [1]=>VAL2 }
array3
{ [0]=>VAL1 [1]=>VAL2 }
}
I've tried, but I could only get it to look like this:
array(1) { [0]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } }
array(2) { [0]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } [1]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } }
array(3) { [0]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } [1]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } [2]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } }
And that's definitely not what I'm aiming for. Nothing seems contained. I need the format specified above.
I'm using the explode function on a string pulled from a file to make this table of arrays (I think you call it that)
Here is the code I'm using that's not working.
$variabledebugging = file("FILE.TXT");//LOOK IN THIS FILE FOR THE NUMBER AND SET IT TO A VAR.
$i=0;
foreach($variabledebugging as $placeholder){
$variabledebuggingtbl[] = explode("\t",$variabledebugging[$i]);
var_dump($variabledebuggingtbl);
$i++;
}
I've tried a couple of different variations, but that's the one I'm using now.
To be clear, that file being pulled (each line as a value in an array) has 2 things written to each line, separated by a tab character, so that's the system I'm going on.
Thank you! I'm sure this is a simple task, I just can't think it through.
Oh and while I'm at is there a way to make debugging more readable?
You ARE getting the right result. The reason it seems wrong is that you are running var_dump inside the loop. And why don't you use the $placeholder variable?
$variabledebugging = file("FILE.TXT");
foreach($variabledebugging as $placeholder){
$variabledebuggingtbl[] = explode("\t", $placeholder);
}
var_dump($variabledebuggingtbl);
I'm not sure what you mean by "making debugging more readable", but if you want some linebreaks and indentation you should just look in the generated HTML code. var_dump do add spacing to make it readable but it is ignored by the web browser. If you don't want to read the HTML source, just add your var_dump to a <pre> element.

Categories