php simplexml node no longer exists : how to get attribute value? - php

After wasting more than 6 hour, I'm posting my problem here.
I'm trying to get simplexmlelement attribute value :
This is my var_dump value :
object(SimpleXMLElement)#5 (1) {
["#attributes"]=>
array(3) {
["type"]=>
string(4) "Rich"
["template"]=>
string(44) "EntityContainer.HeroGeneric_8_1_RTM-7814aaaa"
["disambiguationId"]=>
string(36) "85fa63d3-9596-adb9-b4eb-502273d84f56"
}
}
I want to get ["type"] value "Rich". However i am not able to get that. I've seen a lot of answers and code example before post it here but they did not help.
Actually first time i am trying to use simplexmlelement [Advance code]
My php code
$xml = simplexml_load_file($url);
$xml2 = $xml->channel->item;
foreach ($xml2 as $out_ns)
{
$ns = $out_ns->getNamespaces(true);
$child = $out_ns->children($ns['win']);
var_dump($child); // Value is written above simple xml object
print_r((string) $child->attributes());
}
I want to know what's wrong i have done. I want to achieve type and disambiguationId attribute values.
Error:
Warning: SimpleXMLElement::__toString(): Node no longer exists in E:\xampp\htdocs\ring\dom.php on line 15
Please check my code help me.

You have to check if element exists:
if($child && $child->attributes()) {
print_r($child->attributes());
}

Related

php dynamically created class object has two properties with the same name cant figure out why

Some code I used ot rely on a lot is now creating an object with two properties that have the same name.
I did not think this was even possible to have two properties with the same name and separate values.
I have a function that converts an array to a class object. This method has worked fine for so many applications and I have never encountered this stange problem before.
Below is the function with added var dumps and a die() to stop execution just to get the output of the first object to show you guys.
The params (array is putput below, class = "FA\WheelImage", namespace = "")
protected function arrayToClass($array, $class,$nameSpace=''){
$nameSpaceClassPrefix = (!empty($nameSpace))? "\\$nameSpace\\" : "";
if(!class_exists($nameSpaceClassPrefix . $class)){
echo "<br>ERROR: $class is not a valid object type!<br>";
return false;
}
echo "<pre>";
var_dump($array);
var_dump($this->headings);
$class_name = $nameSpaceClassPrefix . $class;
$class_object = new $class_name();
foreach ($array as $key => $value){
//note: this usually only works if the array is associative first so we have to set the key to be the heading
$key = $this->headings[$key];
//only assign if the class object has the property defined. Move out of condition if you the property created regardless of if the model defines it.
if(!$this->explicit_properties || property_exists($class_object, $key)){
if ($value=="false") $value = false;
if ($value=="true") $value = true;
if ($value=="null") $value = null;
$class_object->{$key} = $value;
}
}
var_dump($class_object);
die("stop");
return $class_object;
}
OUTPUT: original array, headings used for key/property names, the resulting class object.
array(3) {
[0]=>
string(14) "TSW_bathurst_1"
[1]=>
string(3) "TSW"
[2]=>
string(8) "Bathurst"
}
array(3) {
[0]=>
string(8) "image"
[1]=>
string(5) "brand"
[2]=>
string(5) "wheel"
}
object(FA\WheelImage)#162 (4) {
["image"]=>
NULL
["brand"]=>
string(3) "TSW"
["wheel"]=>
string(8) "Bathurst"
["image"]=>
string(14) "TSW_bathurst_1"
}
stop
As you can see the class object ends up with two properties with the exact same name. How is this possible?
How the class object is defined:
namespace FA;
class WheelImage
{
var $image;
var $brand;
var $wheel;
}
NOTE: The headings are coming from a csv file:
//the csv file
image,brand,wheel
TSW_bathurst_1,TSW,Bathurst
TSW_bathurst_2,TSW,Bathurst
TSW_bathurst_3,TSW,Bathurst
TSW_bathurst_4,TSW,Bathurst
//how the headings are loaded
if ($has_headings) $this->headings = fgetcsv($file);//first row is headings
Fixed it by just making a new csv file and manually typing the csv headings.
The original file was saved via excel.
My guess is some sort of text encoding was causing the issue.
Editing the the original file by deleting the headings and typing them again wasn't working but creating a new file and typing it out fixed the issue.
Al-tho I have resolved the issue I'd still love to hear anyone's ideas on why this happened and how to make the some generic code to ignore any weird text encoding in the csv file.
I think possible this might have been a better answer if I was in the situation where recreating the source file wasnt an option.
Remove non-utf8 characters from string

PHP Illegal String Offset Warning

Disclaimer: I'm not a PHP programmer. I don't really consider myself a programmer at all. I was just unfortunate enough to inherit some code that doesn't work.
So I have this code. I believe it was written for PHP4, but we're using PHP5.
// Retrieve project list
$project = new CProject();
$proj = $project->getAllowedRecords( $AppUI->user_id, 'project_id, project_name');
foreach ( $proj as $k => $p ) {
$project_select_list[$k] = $p['project_name'];
}
This is supposed to populate a pick list based on the user's role, but it doesn't work. I get the "illegal string offset" warning on the line inside of the foreach loop. I think understand what it's trying to do, but I don't enough about PHP to fix it. I did a vardump on $proj and it returned this.
array(5) {
[1]=> string(4) "Roof"
[2]=> string(4) "Wall"
[3]=> string(4) "Yard"
[4]=> string(7) "Kitchen"
[5]=> string(8) "Bathroom"
}
Anyone got any hints on how to fix it? Thanks.
This seems to be produced by this:
$p['project_name'];
If $p variable is a string (as the var_dump() said), you don't have an array to access nowhere. The most probably solution is this:
foreach ( $proj as $k => $p ) {
$project_select_list[$k] = $p;
}

Getting Value from Object with Characters in Element Name

I have an object being passed into a function which I have no control over and it is in the below format, with the root being 'entity'.
object(SimpleXMLElement)#6 (1) { ["#attributes"]=> array(2) { ["id"]=> string(2) "12" ["name"]=> string(17) "Test Object Value" } }
Now I'm trying to pull out just the name by using both the below snippets but both output empty values.
entity[0]->name;
and
entity->{'#attributes'}->name;
Is there a special way to deal with characters in element names when the curly brackets format doesn't work?
You need to use attribute() function for getting the attributes in a simpleXML object. Your code should be something like:
$parsed = $simplexmlObject->entity->attribute()->desiredProperty;
Update: Got this technique from a question asked from me, How to parse value `#attribute` from a SimpleXMLObject in PHP
You can get the name attribute as follows:
$name = $entity->attributes()->name;
echo $name;

Accessing a specific XML-node with PHP using SimpleXML

lately i ran into a problem using simplexml.
What i want to do is to get a value of a nested node that occurs multiple times.
The xml looks somewhat like this:
<response>
<album id="123">
[...]
<duration>
<value format="seconds">2576</value>
<value format="mm:ss">42:56</value>
<value format="hh:mm:ss">00:42:56</value>
<value format="xs:duration">PT42M56S</value>
</duration>
[...]
</album>
</response>
Specifically i need the value of the the <value format="hh:mm:ss"> node.
So I have a reference to the object that looks somewhat like this:
$this->webservice->album->duration->value;
Now, if i var_dump this the result will be:
object(SimpleXMLElement)#117 (5) {
["#attributes"]=> array(1) {
["format"]=> string(7) "seconds"
}
[0]=> string(4) "2576"
[1]=> string(5) "42:56"
[2]=> string(8) "00:42:56"
[3]=> string(8) "PT42M56S"
}
I do not understand this output, since it takes the format-attribute of the first node (seconds) and continues with the node-values in the array, while ignoring the format-attribute of the following nodes completely.
Furthermore, if i do the following:
$this->webservice->album->duration->value[2];
it results in:
object(SimpleXMLElement)#108 (1) {
["#attributes"]=> array(1) {
["format"]=> string(8) "hh:mm:ss"
}
}
where i haven't got a value to address at all.
I tried to use xpath instead too in the following way:
$this->webservice->album->duration->xpath('value[#format="hh:mm:ss"]');
which results in:
array(1) {
[0]=> object(SimpleXMLElement)#116 (1) {
["#attributes"]=> array(1) {
["format"]=> string(8) "hh:mm:ss"
}
}
}
So my question is:
What am I doing wrong? xD
Thanks in advance for any helpful advice :)
Your mistake is in trusting var_dump too completely, rather than trying to use the elements based on the examples in the manual.
On your first attempt, you accessed $duration_node->value; this can be used in a few different ways:
if you iterate over it with foreach($duration_node->value as $value_node), you get each of the <value> elements in turn
you can access specific elements by index, e.g. $duration_node->value[2] for the 3rd element
if you treat it as a single element, SimpleXML assumes you want the first element, i.e. echo $duration_node->value is the same as echo $duration_node->value[0]
Your second example worked fine - it found the <value> element with an attribute format="hh:mm:ss". The xpath() method always returns an array, so you need to check that it's not empty then look at the first element.
Once you have the right element, accessing its text content is as simple as casting it to a string ((string)$foo), or passing it to something that always needs a string (e.g. echo).
So this would work:
$xpath_results = $this->webservice->album->duration->xpath('value[#format="hh:mm:ss"]');
if ( count($xpath_results) != 0 ) {
$value = (string)$xpath_results[0];
}
As would this:
foreach ( $this->webservice->album->duration->value as $value_node ) {
if ( $value_node['format'] == 'hh:mm:ss' ) {
$value = (string)$value_node;
break;
}
}

PHP object array navigation

I'm pulling data from a Blogger RSS feed. I have most of it narrowed down how I would like it to be, except for one thing. In the following object, how would I get the string in the term section? I've tried about every syntax I can think of, but I honestly have run out of ideas.
object(SimpleXMLElement)#7 (1) {
["#attributes"]=>
array(2) {
["scheme"]=>
string(31) "http://www.blogger.com/atom/ns#"
["term"]=>
string(7) "happens"
}
}
I've tried to var_dump $item->attributesand $item->#attributes with no luck.
Use the attributes() method:
$atts = $xml->attributes();
echo $atts['term'];
Alternatively, you could also use:
$xml->attributes()->{'term'};
var_dump($object->{'#attributes'}['term']);
or
$tmp = '#attributes';
var_dump($object->{$tmp}['term']);

Categories