PHP Accessing SimpleXMLElement Object array keys - php

In the following SimpleXMLElement Object $results, I would like to remove the element with ID 13011146 from the TEST array. I'm not sure how to properly access the array key with value 1, so I'm using a counter $i, but that gives me an error Node no longer exists, pointing to the foreach line.
TL;DR: How do you unset $result->TEST[1] ?
SimpleXMLElement Object
(
[TEST] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[ID] => 13011145
)
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[ID] => 13011146
)
)
)
)
PHP:
$i = 0;
foreach($results->TEST as $key => $value) {
if( (string)$value['ID'] == 13011146 ) {
unset($results->TEST[$i]);
}
$i++;
}

try this
$node = $results->children();
unset($node[1]);

foreach($results->TEST->children() as $key => $value) {
$attributes = $value->attributes();
foreach($attributes as $a => $b) {
if (( (string)$a == 'ID' ) && ( (string)$b == '13011146' )) {
unset($results->TEST[$key]);
}
}
}

a more elegant way; it gives you the same results without using $attributes[ '#attributes' ] :
$attributes = current($element->attributes());
For specific key/value pair, we can use like:
$attributes = current($value->attributes()->NAME);
Hope it helps !

Try this:
$sxe = new SimpleXMLElement($xml);
foreach ($sxe->children() as $child){
foreach($child as $key=>$item){
echo $key.': '.$item.'<br />';
}
}

Related

How to parse arrays with different levels PHP

In a foreach loop i would like to compare [name] value beetween different arrays but they have not the same levels.
Array(
[array1] => Array
(
[0] => WP_Term Object
(
[name] => Plafond
)
)
[array2] => WP_Term Object
(
[name] => Chaudière
)
[array3] => Array
(
[0] => WP_Term Object
(
[name] => Pla
)
[1] => WP_Term Object
(
[name] => Toc
)
)
)
I don't know how could i get the [name] in the same loop whereas levels are different.
I have tried to make :
foreach( $fields as $name => $value )
{
echo $value->name; }
Should i add another loop in the first loop ?
thanks
So your data looks like this:
$json = '{"array1":[{"name":"Plafond"}],"array2":{"name":"Chaudière"},"array3":[{"name":"Pla"},{"name":"Toc"}]}';
$array = json_decode($json);
If you don't know how deep it will go, a simple recursive function should work. Perhaps something like this:
function get_name($o, &$output) {
if (is_array($o)) {
foreach($o as $v) {
get_name($v, $output);
}
} elseif (property_exists($o, "name")) {
$output[] = $o->name;
}
}
$output = [];
foreach ($array as $v) {
get_name($v, $output);
}
If you data is going to look like the sample you provided (i.e. it will always be first or second level) then you don't need to worry about recursion.
$output = [];
foreach ($array as $k=>$v) {
if (is_array($v)) {
foreach ($v as $k2=>$v2) {
$output[] = $v2->name;
}
} else {
$output[] = $v->name;
}
}
Either way, your output values are all in the $output array:
print_r($output);
Output:
Array
(
[0] => Plafond
[1] => Chaudière
[2] => Pla
[3] => Toc
)
You can use array_map, array_key_exists to retrive the name index from the array
$jsonFormat = '{"array1":[{"name":"Plafond"}],"array2":{"name":"Chaudière"},"array3":[{"name":"Pla"},{"name":"Toc"}]}';
$jsonArray = json_decode($jsonFormat,true);
$res = [];
array_map(function($v) use (&$res){
if(array_key_exists('name', $v)){
$res[] = $v['name'];
}else{
foreach($v as $_key => $_value){
$res[] = $_value['name'];
}
}
}, $jsonArray);
echo '<pre>';
print_r($res);
Result:-
Array
(
[0] => Plafond
[1] => Chaudière
[2] => Pla
[3] => Toc
)
You can use $res to compare the names.

How to fetch non-empty Array from an Array

The Array contains some non-empty arrays . i need to fetch respective non-empty array and print the data . eg: array 2 has variable as importTroubles->troubleMessage how can i print that?
Array
(
[0] => stdClass Object
(
)
[1] => stdClass Object
(
)
[2] => stdClass Object
(
[return] => stdClass Object
(
[failureMessage] =>
[importTroubles] => stdClass Object
(
[kind] => ParseError
[rowNumber] => 1
[troubleMessage] => Field "number1" has invalid value: "+16046799329". Invalid phone number //need to print this..
)
[keyFields] => number1
[uploadDuplicatesCount] => 0
[uploadErrorsCount] => 1
[warningsCount] => stdClass Object
(
)
[callNowQueued] => 0
[crmRecordsInserted] => 0
[crmRecordsUpdated] => 2
[listName] => new camp from CRM1-TargetList-CRM
[listRecordsDeleted] => 0
[listRecordsInserted] => 2
)
)
[3] => stdClass Object
(
)
[4] => stdClass Object
(
)
)
im trying with this method :
foreach($result as $object) {
foreach ($object as $items) {
if($items !== '')
{
foreach ($items as $item) {
echo "ERROR".$item->troubleMessage;
}
}
}
}
Thanks for your efforts
Make use of php function empty()
Change your if condition as in below code :
foreach($result as $object) {
foreach ($object as $items) {
if( !empty($items) )
{
foreach ($items as $item) {
if( isset($item->troubleMessage) )
{
echo "ERROR".$item->troubleMessage;
}
}
}
}
}
Now it will echo only if $items has values.
You don't have to iterate each object if you're only looking for a single specific item nested within it. You can just refer to that item directly.
foreach ($your_array as $object) {
if (isset($object->return->importTroubles->troubleMessage)) {
echo $object->return->importTroubles->troubleMessage;
}
}
If you check if that specific nested object variable is set, it will ignore any empty objects.
change your if($items !== '') to if(!empty($items)) or if($items) or if($items[0]) hope it helps
You could use Collection
use Illuminate\Support\Collection;
$collection = new Collection($result);
$items = $collection->filter(function($object) {
return isset($object->return->importTroubles->troubleMessage);
})->map(function($object) {
return $object->return->importTroubles->troubleMessage;
});

Get to leaf in multidimension array

I have array structure where i must get leaf.
Example
First type of array
[name] => long_desc
[values] => Array
(
[0] => Array
(
[values] => xxx
)
)
)
or
(
[name] => long_desc
[values] => Array
(
[0] => Array
(
[name] => span
[values] => Array
(
[0] => Array
(
[values] => xxx
)
)
)
How to get value what name xxx? My array have longer depth and using foreach many times not work fine. I was try recursivearrayiterator but not help.
Try array_walk_recursive() function:
function testArrayItem($item, $key)
{
if ( $item == "xxx" ) {
echo "Found xxx on key {$key}";
}
}
array_walk_recursive($array, 'testArrayItem');
EDIT:
If you want to get entire branch, which leads to the leaf you can recursively iterate through it:
function getPathToLeafRecursive(array $input, array &$branch)
{
foreach ( $input as $key => $item ) {
if ( 'xxx' == $item ) {
$branch[] = $key;
return true;
}
if ( is_array($item) ) {
$res = getPathToLeafRecursive($item, $branch);
if ( $res ) {
$branch[] = $key;
return true;
}
}
}
return false;
}
$found_branch = array();
getPathToLeafRecursive($array, $found_branch);
$found_branch = array_reverse($found_branch);
var_export($found_branch);
Here's how to find the leaf node, without depending on the name of the key. It's rather primitive and could use some OOP, but it demonstrates the basic algo:
$array = array(
array('name' => 'span',
'values' => array('values' => 'xxx', array('values' => 'yyy')),
'stuff' => '123'
)
);
$deepest_depth = 0;
$deepest_node = null;
find_leaf($array, 0);
function find_leaf($array, $current_depth) {
global $deepest_depth, $deepest_node;
do {
$current_node = current($array);
if (is_array($current_node)) {
find_leaf($current_node, $current_depth+1);
} else {
if ($deepest_node === null || $current_depth > $deepest_depth) {
$deepest_depth = $current_depth;
$deepest_node = $current_node;
}
}
next($array);
} while ($current_node !== FALSE);
}
echo $deepest_node;
What is this xxx value? Do you know the content and you just want to know that it is in the Array?
In that case you can use the RecursiveArrayIterator with the RecursiveFilterIterator.
If you want to get all "values" keys that are leafs, then you can use the RecursiveFilterIterator too, but checking for "values" that are scalar for example.

Strip an XML object of its object status, and save the value contained inside

I have an object which contains an array, which contains an array, which contains an object:
stdClass Object
(
[path] => Array
(
[0] => Array
(
[0] => SimpleXMLElement Object
(
[0] => 44.6451471575972
)
)
)
)
What I need to turn that into is this:
stdClass Object
(
[path] => Array
(
[0] => Array
(
[0] => 44.6451471575972
)
)
)
Basically I need to get rid of that object, but save the value in that object. Using PHP, how do I do this?
EDIT: Here the code I am using to create the array:
$xml = simplexml_load_file('/Users/jasonburton/Sites/walkabout/csv-importer/xml/'.$old_route_id.'.xml');
$nodes = $xml->xpath('/markers/line/*');
$json = new stdClass;
$json->path = array();
foreach($nodes as $node){
foreach($node->attributes() as $index=>$value){
$values[] = $value;
if(count($values) == 2){
$json->path[] = array($values[0], $values[1]);
unset($values);
$values = array();
}
}
}
print_r($json);
$value is what contains the SimpleXMLObject that needs to be converted into the value.
Thanks!
Type cast $value with string: $values[] = (string)$value;

rename multiple attributes with simpleXML

<root>
<gallery name="First"/>
<gallery name="Second"/>
<gallery name="Third"/>
</root>
I'm trying to rename multiple "name" attributes at once:
$rename = array();
foreach($_POST['name'] as $value) {
$rename[] = $value;
}
$objXML = new SimpleXMLElement(XML_FILE_NAME, null, true);
$gallery = $objXML->xpath('/root/gallery/#name');
print_r($gallery);
print_r($rename);
$objXML->asXML(XML_FILE_NAME);
Returns:
Array ( [0] => SimpleXMLElement Object ( [#attributes] => Array ( [name] => First ) ) [1] => SimpleXMLElement Object ( [#attributes] => Array ( [name] => Second ) ) [2] => SimpleXMLElement Object ( [#attributes] => Array ( [name] => Third ) ) )
Array ( [0] => First New [1] => Second New [2] => Third New )
How can I get php to save the New values back to the XML? Does it need another foreach loop? The code seems to be getting too complex already.
I'm trying this, but no dice:
foreach( $objXML->xpath('/root/gallery/#name') as $gallery ) {
$gallery = $_POST['name'];
}
Simplexml is buid to returns node only. That's weird, but '/root/gallery/#name' and '/root/gallery'.
These two queries
$aList = $objXML->xpath('/root/gallery/#name');
$bList = $objXML->xpath('/root/gallery');
will return the same instances
for($i=0, $count=count($aList); $i<$count; $i++) {
$a = $aList[$i];
$b = $aList[$i];
var_dump($a==$b); // true
}
So the only way for changing the attribute of a node is with the array syntaxe
foreach($aList as $node) {
$node['name'] = 'foo' . $i;
}
var_dump($objXML);

Categories