php simplexml - string as object - php

Hoping somebody can advise on an issue I have with simplexml.
I need to specify the paths for various nodes but I'm not sure if this is possible.
$xml = new SimpleXMLElement($xmlstr);
$image1 = 'images->image[0]->image';
foreach ($xml->record as $record) {
echo $record->$image1; // i need this be be recognised as $record->images->image[0]->image
}
Hope this makes sense! Thanks

You can use an array for this:
$xml = new SimpleXMLElement($xmlstr);
$levels = array('images', array('key' => 'image', 'index' => 0), 'image');
foreach ($xml->record as $record) {
$obj = $record;
foreach($levels as $level) {
if(is_array($level))
$obj = $obj->{$level['key']}[$level['index']];
else
$obj = $obj->$level;
}
echo $obj;
}
This builds up the hierarchy by reassigning $obj equal to itself -> whatever is next in the array.
PHP cannot interpolate array indices in strings, so if you need to use them, just use an associate array as shown above. :-)

Related

How I coul get a JSON like this?

I need to get a JSON with arrays, how I could do it?
//JSON I need to get
{"keywords":[{"keyword":"kw1", "tags":["sample"]},{"keyword":"kw2", "tags":["sample, sample2"]}]}
//For now, I got this
$keywords = array("kw1", "kw2");
$tags= array("sample", "sample2");
function Keywords($keywords, $tags){
$fields= array("keywords" => $keywords);
$jsondata = json_encode($fields);
print_r($jsondata );
}
//output
{"keywords":["kw1","kw2"]}
I expect the output like this:
{"keywords":[{"keyword":"kw1", "tags":["sample"]},{"keyword":"kw2", "tags":["sample, sample2"]}]}
Assuming tags in the first element of your example is supposed to be ["sample, sample2"] as well (otherwise you would really have to explain by what logic you want to achieve at the result as shown) …
$keywords = array("kw1", "kw2");
$tags= array("sample", "sample2");
$result = new StdClass;
$result->keywords = [];
foreach($keywords as $keyword) {
$temp = new StdClass;
$temp->keyword = $keyword;
$temp->tags = [];
foreach($tags as $tag) {
$temp->tags[] = $tag;
}
$result->keywords[] = $temp;
}
echo json_encode($result);
Basically two nested loops over the keywords and the tags, and inside a new temporary object is created an then appended to the result array.

How to add property to object (SimpleXMLElement) using loop (reference)

I have code that retrieves list of data in Object $xmlContent
$source = 'http://www.bnm.org/en/official_exchange_rates?get_xml=1&date=23.11.2016';
$xmlString = file_get_contents($source);
$xmlContent = new \SimpleXMLElement($xmlString);
How can I add property by reference to the object like we can do this in case of Array?
foreach ($xmlContent as $k => &$v) {
$v['test_property'] = any_function($v->value);
}
This code will not work beacuse I can't change and add any values by reference to Object.
How can I add new items to object in this case?
You can use the addChild function for that:
$v; // $v is a SimpleXMLElement object
$v->addChild('nodeName', 'nodeContent');
foreach ($xmlContent as $k => $v) {
$v->addAttribute('test_property', any_function($v->value));
}

Create nested objects from CSV

I have a CSV file which needs to be processed into objects.
I can open the CSV file and get all the contents that I want, no problem there. I need to match the contents of the CSV file by headers into objects. For example:
Name | Address.Street | Address.Country | Notes.Example.Value
Object->Name
Object->Address
Object->Notes
etc.
How would I handle this dynamically, not knowing what the headers are going to be beforehand?
Essentially I want to turn a string, like "Prop.Prop.Prop.etc" into a nested object.
$headers = array(); // First row of CSV.
$row = array(); // Current row of CSV.
$record = new StdClass();
foreach ($row as $key => $value) {
$properties = explode('.', $headers[$key]);
if (count($properties > 1)) {
// ???
}
else {
$record->{$properties[0]} = $value;
}
}
This should be done through a recursion. If the property you're parsing has only one level of depth, then you set the object key as a value. (which you're already doing)
If it has two or more levels, you shift the first element of the property array and recurse on the remaining levels.
Elaborating in your example:
<?php
$headers=[
'Name',
'Email',
'Address.Street',
'Address.Country',
'Notes.Example.Value'
];
$row=[
'john',
'john#gmail.com',
'beale street',
'US',
'180'
];
function setObject(&$object, $properties, $value) {
$name=array_shift($properties);
if(count($properties)===0) {
return $object->{$name} = $value;
} else {
// if this property isn't set, we declare it as a new object
if(!isset($object->{$name}) || !is_object($object->{$name})) $object->{$name} = new StdClass();
return setObject($object->{$name}, $properties,$value);
}
}
$record = new StdClass();
foreach($row as $key=>$value) {
$properties = explode('.', $headers[$key]);
setObject($record, $properties, $value);
}
echo '<pre>';
print_r($record);
echo '</pre>';
This is probably not the most elegant solution. With a bit of work you could avoid passing the object by reference back and forth.

Foreach Array not being created correctly

I am generating an array using a foreach like so...
<?php
$docs = array();
$media = get_attached_media('image');
foreach($media as $medias) {
$docs[] = $medias->guid;
}
$images = serialize(array('docs' => $docs));
print_r($images);
?>
The output I am getting is...
a:1:{s:4:docs";a:3:{i:0;s:62:"http://www.example.com/image1.jpg";i:1;s:62:"http://www.example.com/image2.jpg";i:2;s:62:"http://www.example.com/image3.jpg";}}"
But what I need is...
a:1:{s:4:"docs";a:4:{i:0;a:1:{s:15:"property_imgurl";s:35:"http://wwww.example.com/image1.jpg";}i:1;a:1:{s:15:"property_imgurl";s:35:"http://wwww.example.com/image2.jpg";}i:2;a:1:{s:15:"property_imgurl";s:35:"http://wwww.example.com/image3.jpg";}i:3;a:1:{s:15:"property_imgurl";s:35:"http://wwww.example.com/image4.jpg";}}}
Where am I going wrong?
It looks like your expecting $medias->guid to be an array, but it's a string. I believe your going to need to provide an array value when pushing into your array. This should work for you:
$docs = array();
$media = get_attached_media('image');
foreach($media as $medias) {
$docs[] = array("property_imgurl" => $medias->guid);
}
$images = serialize(array('docs' => $docs));
print_r($images);

store objects in an array during foreach?

I am looking to store some objects in an array during a foreach loop. The problem is creating a unique object each time. I have to have some kind of index appending the name of each object. Here is what I have:
function table_rows($html) {
$dom = new Zend_Dom_Query($html);
$table_rows = $dom->query('tr');
$check_array = array();
foreach ($table_rows as $key=>$table_row) {
($check_object . $key) = new check_class;
($check_object . $key)->check_method1($table_row);
($check_object . $key)->check_method2($table_row);
($check_object . $key)->check_method3($table_row);
$check_array[] = (check_object . $key);
}
}
Am I even close?
You could use variables for that:
function table_rows($html) {
$dom = new Zend_Dom_Query($html);
$table_rows = $dom->query('tr');
$check_array = array();
foreach ($table_rows as $key=>$table_row) {
$object = new check_class;
$object->check_method1($table_row);
$object->check_method2($table_row);
$object->check_method3($table_row);
$check_array[] = $object;
}
}
Of course naming the variable for an object instance $object is not very descriptive, but I hope you get the idea.
This works because the first assignment in the for-loop overwrites the "old" instance, so $object unique for each iteration.
In case Jared Drake is right and what you mean is unique array keys, not object (variable) names.
$dom = new Zend_Dom_Query($html);
$table_rows = $dom->query('tr');
$check_array = array();
foreach ($table_rows as $key=>$table_row) {
$check_object = new check_class;
$check_object->check_method1($table_row);
$check_object->check_method2($table_row);
$check_object->check_method3($table_row);
$check_array['check_object' . $key] = $check_object;
}
}
Maybe I'm misunderstanding the question, but can't you just use the array_push method to add each object to the end of the array in your foreach loop?

Categories