I'm struggling with an array in my SimpleXMLElement Object. Somehow I don't get the expected result when I print the array $node->reference.
print_r($node); shows:
SimpleXMLElement Object
(
[reference] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[resourceIdentifier] => 52chgb7f-1a00-4eaf-ac8a-5d4557f9796a
)
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[resourceIdentifier] => 52cbccc3-b754-4e88-9238-5d5257f9796a
)
)
)
)
But print_r($node->reference); and print_r($node->reference->children()); shows:
SimpleXMLElement Object
(
[#attributes] => Array
(
[resourceIdentifier] => 52chgb7f-1a00-4eaf-ac8a-5d4557f9796a
)
)
I expect to see:
Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[resourceIdentifier] => 52chgb7f-1a00-4eaf-ac8a-5d4557f9796a
)
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[resourceIdentifier] => 52cbccc3-b754-4e88-9238-5d5257f9796a
)
)
)
Edit
Here is some code to reproduce:
<?php
$xml = '<?xml version="1.0" encoding="UTF-8" ?>
<items>
<item>
<reference resourceIdentifier="52chgb7f-1a00-4eaf-ac8a-5d4557f9796a" />
<reference resourceIdentifier="52cbccc3-b754-4e88-9238-5d5257f9796a" />
</item>
<item>
<reference resourceIdentifier="52chgb7f-1a00-4eaf-ac8a-5d4557f9796a" />
</item>
<item>
<reference resourceIdentifier="52chgb7f-1a00-4eaf-ac8a-5d4557f9796a" />
<reference resourceIdentifier="52chgb7f-1a00-4eaf-ac8a-5d4557f9796a" />
<reference resourceIdentifier="52cbccc3-b754-4e88-9238-5d5257f9796a" />
</item>
</items>';
$items = new \SimpleXMLElement($xml);
foreach ($items as $item) {
echo '<h1>Item</h1>';
echo '<pre>';
print_r($item);
print_r($item->reference); // Returns always 1 SimpleXMLElement Object?
print_r($item->reference->children()); // Returns always 1 SimpleXMLElement Object?
echo '</pre>';
}
The simple answer is: don't rely on print_r. The thing with SimpleXML is that it uses a lot of, for want of a better word, "magic", and print_r (and var_dump, var_export, and pretty much any other generic debug or serialize function) doesn't show you how it will behave. Also, and this is really important, a SimpleXMLElement does not contain any arrays.
I wrote a dedicated debug function which, while not perfect, does a better job of recursing through SimpleXML objects than the native ones.
The reason for this specific behaviour is that you can use $node->reference to refer to either the list of all children called reference, or the first such child. The following are all equivalent:
// Access as iterable list
foreach ( $node->reference as $ref ) {
echo $ref['resourceIdentifier'];
// only loop once
break;
}
// Access as numerically indexed array
echo $node->reference[0]['resourceIdentifier'];
// Access first item by default
echo $node->reference['resourceIdentifier'];
This is extremely handy when you have a document that is "deep but narrow", e.g.
$xml = simplexml_load_string('<foo><bar><baz><quux hello="world" /></baz></bar></foo>');
echo $xml->bar->baz->quux['hello']; // world
Rather than you having to check whether a node is unique or multiple, SimpleXML just lets you write such an expression and ignore any multiples:
$xml = simplexml_load_string('<foo><bar><baz><quux hello="world" /><quux ignored="true" /></baz></bar><bar>ignored</bar></foo>');
echo $xml->bar->baz->quux['hello']; // world
Related
I am having a problem accessing the #attribute section of my SimpleXML object. When I var_dump the entire object, I get the correct output, and when I var_dump the rest of the object (the nested tags), I get the correct output, but when I follow the docs and var_dump $xml->OFFICE->{'#attributes'}, I get an empty object, despite the fact that the first var_dump clearly shows that there are attributes to output.
Anyone know what I am doing wrong here/how I can make this work?
Try this
$xml->attributes()->Token
You can get the attributes of an XML element by calling the attributes() function on an XML node. You can then var_dump the return value of the function.
More info at php.net
http://php.net/simplexmlelement.attributes
Example code from that page:
$xml = simplexml_load_string($string);
foreach($xml->foo[0]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
I used before so many times for getting #attributes like below and it was a little bit longer.
$att = $xml->attributes();
echo $att['field'];
It should be more easy and you can get attributes following format only at once:
Standard Way - Array-Access Attributes (AAA)
$xml['field'];
Other alternatives are:
Right & Quick Format
$xml->attributes()->{'field'};
Wrong Formats
$xml->attributes()->field;
$xml->{"#attributes"}->field;
$xml->attributes('field');
$xml->attributes()['field'];
$xml->attributes->['field'];
$xml = <<<XML
<root>
<elem attrib="value" />
</root>
XML;
$sxml = simplexml_load_string($xml);
$attrs = $sxml->elem->attributes();
echo $attrs["attrib"]; //or just $sxml->elem["attrib"]
Use SimpleXMLElement::attributes.
Truth is, the SimpleXMLElement get_properties handler lies big time. There's no property named "#attributes", so you can't do $sxml->elem->{"#attributes"}["attrib"].
You can just do:
echo $xml['token'];
If you're looking for a list of these attributes though, XPath will be your friend
print_r($xml->xpath('#token'));
It helped me to convert the result of simplexml_load_file($file) into a JSON Structure and decode it back:
$xml = simplexml_load_file("$token.xml");
$json = json_encode($xml);
$xml_fixed = json_decode($json);
$try1 = $xml->structure->{"#attributes"}['value'];
print_r($try1);
>> result: SimpleXMLElement Object
(
)
$try2 = $xml_fixed->structure->{"#attributes"}['value'];
print_r($try2);
>> result: stdClass Object
(
[key] => value
)
Unfortunately I have a unique build (stuck with Gentoo for the moment) of PHP 5.5, and what I found was that
$xml->tagName['attribute']
was the only solution that worked. I tried all of Bora's methods above, including the 'Right & Quick' format, and they all failed.
The fact that this is the easiest format is a plus, but didn't enjoy thinking I was insane trying all of the formats others were saying worked.
Njoy for what its worth (did I mention unique build?).
I want to extract string (just Song title and Artist name) from external xml file: https://nostalgicfm.ro/NowOnAir.xml
This form of xml:
<Schedule System="Jazler">
<Event status="happening" startTime="20:31:20" eventType="song">
<Announcement Display=""/>
<Song title="Let It Be ">
<Artist name="Beatles">
<Media runTime="265.186"/>
<Expire Time="20:35:45"/>
</Artist>
</Song>
</Event>
</Schedule>
I try this code PHP but i don't know how to extract name & title...like "Beatles - Let It Be"
<?php
$url = "https://nostalgicfm.ro/NowOnAir.xml";
$xml = simplexml_load_file($url);
print_r($xml);
?>
Result is an Oject:
SimpleXMLElement Object ( [#attributes] => Array ( [System] => Jazler ) [Event] => SimpleXMLElement Object ( [#attributes] => Array ( [status] => happening [startTime] => 20:51:21 [eventType] => song ) [Announcement] => SimpleXMLElement Object ( [#attributes] => Array ( [Display] => ) ) [Song] => SimpleXMLElement Object ( [#attributes] => Array ( [title] => If You Were A Sailboat ) [Artist] => SimpleXMLElement Object ( [#attributes] => Array ( [name] => Katie Melua ) [Media] => SimpleXMLElement Object ( [#attributes] => Array ( [runTime] => 228.732 ) ) [Expire] => SimpleXMLElement Object ( [#attributes] => Array ( [Time] => 20:55:09 ) ) ) ) ) )
Resolved it myself:
<?php
$url = 'https://nostalgicfm.ro/NowOnAir.xml';
$xml = simplexml_load_file($url);
foreach ( $xml->Event->Song->Artist->attributes() as $tag => $value );
foreach ( $xml->Event->Song->attributes() as $tag => $value1 ) {
echo $value." - ".$value1.PHP_EOL; }
?>
I have the following xml file
<?xml version="1.0" encoding="UTF-8"?>
<data>
<item name="general.global.Event"><![CDATA[EVENT!]]></item>
<item name="general.global.CompanyName"><![CDATA[some name]]></item>
<item name="general.global.CompanyImprint"><![CDATA[Legal information]]></item>
</data>
and my code is as follows
$xml = simplexml_load_file("general.xml") or die("Error: Cannot create object");
print_r($xml);
and my output is missing the CDATA.. how?
SimpleXMLElement Object
(
[item] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[name] => general.global.Event
)
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[name] => general.global.CompanyName
)
)
[2] => SimpleXMLElement Object
(
[#attributes] => Array
(
[name] => general.global.CompanyImprint
)
)
)
)
Text nodes are not exposed with print_r.
You can see the data there is you look at it explicitly:
print $xml->item[0];
The CDATA is being read, read this answer and you'll see that if you print_r($xml->asXML()); The parser recompiles the CDATA information just fine.
For some reason, PHP's var_dump and print_r don't have accurate representation of XML objects. Try this and you can still access the data:
foreach ($xml->item as $item) {
if ('general.global.CompanyImprint' === (string)$item['name']) {
var_dump((string)$item);
}
}
// prints
string(17) "Legal information"
I am having a problem accessing the #attribute section of my SimpleXML object. When I var_dump the entire object, I get the correct output, and when I var_dump the rest of the object (the nested tags), I get the correct output, but when I follow the docs and var_dump $xml->OFFICE->{'#attributes'}, I get an empty object, despite the fact that the first var_dump clearly shows that there are attributes to output.
Anyone know what I am doing wrong here/how I can make this work?
Try this
$xml->attributes()->Token
You can get the attributes of an XML element by calling the attributes() function on an XML node. You can then var_dump the return value of the function.
More info at php.net
http://php.net/simplexmlelement.attributes
Example code from that page:
$xml = simplexml_load_string($string);
foreach($xml->foo[0]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
I used before so many times for getting #attributes like below and it was a little bit longer.
$att = $xml->attributes();
echo $att['field'];
It should be more easy and you can get attributes following format only at once:
Standard Way - Array-Access Attributes (AAA)
$xml['field'];
Other alternatives are:
Right & Quick Format
$xml->attributes()->{'field'};
Wrong Formats
$xml->attributes()->field;
$xml->{"#attributes"}->field;
$xml->attributes('field');
$xml->attributes()['field'];
$xml->attributes->['field'];
$xml = <<<XML
<root>
<elem attrib="value" />
</root>
XML;
$sxml = simplexml_load_string($xml);
$attrs = $sxml->elem->attributes();
echo $attrs["attrib"]; //or just $sxml->elem["attrib"]
Use SimpleXMLElement::attributes.
Truth is, the SimpleXMLElement get_properties handler lies big time. There's no property named "#attributes", so you can't do $sxml->elem->{"#attributes"}["attrib"].
You can just do:
echo $xml['token'];
If you're looking for a list of these attributes though, XPath will be your friend
print_r($xml->xpath('#token'));
It helped me to convert the result of simplexml_load_file($file) into a JSON Structure and decode it back:
$xml = simplexml_load_file("$token.xml");
$json = json_encode($xml);
$xml_fixed = json_decode($json);
$try1 = $xml->structure->{"#attributes"}['value'];
print_r($try1);
>> result: SimpleXMLElement Object
(
)
$try2 = $xml_fixed->structure->{"#attributes"}['value'];
print_r($try2);
>> result: stdClass Object
(
[key] => value
)
Unfortunately I have a unique build (stuck with Gentoo for the moment) of PHP 5.5, and what I found was that
$xml->tagName['attribute']
was the only solution that worked. I tried all of Bora's methods above, including the 'Right & Quick' format, and they all failed.
The fact that this is the easiest format is a plus, but didn't enjoy thinking I was insane trying all of the formats others were saying worked.
Njoy for what its worth (did I mention unique build?).
I want to extract string (just Song title and Artist name) from external xml file: https://nostalgicfm.ro/NowOnAir.xml
This form of xml:
<Schedule System="Jazler">
<Event status="happening" startTime="20:31:20" eventType="song">
<Announcement Display=""/>
<Song title="Let It Be ">
<Artist name="Beatles">
<Media runTime="265.186"/>
<Expire Time="20:35:45"/>
</Artist>
</Song>
</Event>
</Schedule>
I try this code PHP but i don't know how to extract name & title...like "Beatles - Let It Be"
<?php
$url = "https://nostalgicfm.ro/NowOnAir.xml";
$xml = simplexml_load_file($url);
print_r($xml);
?>
Result is an Oject:
SimpleXMLElement Object ( [#attributes] => Array ( [System] => Jazler ) [Event] => SimpleXMLElement Object ( [#attributes] => Array ( [status] => happening [startTime] => 20:51:21 [eventType] => song ) [Announcement] => SimpleXMLElement Object ( [#attributes] => Array ( [Display] => ) ) [Song] => SimpleXMLElement Object ( [#attributes] => Array ( [title] => If You Were A Sailboat ) [Artist] => SimpleXMLElement Object ( [#attributes] => Array ( [name] => Katie Melua ) [Media] => SimpleXMLElement Object ( [#attributes] => Array ( [runTime] => 228.732 ) ) [Expire] => SimpleXMLElement Object ( [#attributes] => Array ( [Time] => 20:55:09 ) ) ) ) ) )
Resolved it myself:
<?php
$url = 'https://nostalgicfm.ro/NowOnAir.xml';
$xml = simplexml_load_file($url);
foreach ( $xml->Event->Song->Artist->attributes() as $tag => $value );
foreach ( $xml->Event->Song->attributes() as $tag => $value1 ) {
echo $value." - ".$value1.PHP_EOL; }
?>
I am having a problem accessing the #attribute section of my SimpleXML object. When I var_dump the entire object, I get the correct output, and when I var_dump the rest of the object (the nested tags), I get the correct output, but when I follow the docs and var_dump $xml->OFFICE->{'#attributes'}, I get an empty object, despite the fact that the first var_dump clearly shows that there are attributes to output.
Anyone know what I am doing wrong here/how I can make this work?
Try this
$xml->attributes()->Token
You can get the attributes of an XML element by calling the attributes() function on an XML node. You can then var_dump the return value of the function.
More info at php.net
http://php.net/simplexmlelement.attributes
Example code from that page:
$xml = simplexml_load_string($string);
foreach($xml->foo[0]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
I used before so many times for getting #attributes like below and it was a little bit longer.
$att = $xml->attributes();
echo $att['field'];
It should be more easy and you can get attributes following format only at once:
Standard Way - Array-Access Attributes (AAA)
$xml['field'];
Other alternatives are:
Right & Quick Format
$xml->attributes()->{'field'};
Wrong Formats
$xml->attributes()->field;
$xml->{"#attributes"}->field;
$xml->attributes('field');
$xml->attributes()['field'];
$xml->attributes->['field'];
$xml = <<<XML
<root>
<elem attrib="value" />
</root>
XML;
$sxml = simplexml_load_string($xml);
$attrs = $sxml->elem->attributes();
echo $attrs["attrib"]; //or just $sxml->elem["attrib"]
Use SimpleXMLElement::attributes.
Truth is, the SimpleXMLElement get_properties handler lies big time. There's no property named "#attributes", so you can't do $sxml->elem->{"#attributes"}["attrib"].
You can just do:
echo $xml['token'];
If you're looking for a list of these attributes though, XPath will be your friend
print_r($xml->xpath('#token'));
It helped me to convert the result of simplexml_load_file($file) into a JSON Structure and decode it back:
$xml = simplexml_load_file("$token.xml");
$json = json_encode($xml);
$xml_fixed = json_decode($json);
$try1 = $xml->structure->{"#attributes"}['value'];
print_r($try1);
>> result: SimpleXMLElement Object
(
)
$try2 = $xml_fixed->structure->{"#attributes"}['value'];
print_r($try2);
>> result: stdClass Object
(
[key] => value
)
Unfortunately I have a unique build (stuck with Gentoo for the moment) of PHP 5.5, and what I found was that
$xml->tagName['attribute']
was the only solution that worked. I tried all of Bora's methods above, including the 'Right & Quick' format, and they all failed.
The fact that this is the easiest format is a plus, but didn't enjoy thinking I was insane trying all of the formats others were saying worked.
Njoy for what its worth (did I mention unique build?).
I want to extract string (just Song title and Artist name) from external xml file: https://nostalgicfm.ro/NowOnAir.xml
This form of xml:
<Schedule System="Jazler">
<Event status="happening" startTime="20:31:20" eventType="song">
<Announcement Display=""/>
<Song title="Let It Be ">
<Artist name="Beatles">
<Media runTime="265.186"/>
<Expire Time="20:35:45"/>
</Artist>
</Song>
</Event>
</Schedule>
I try this code PHP but i don't know how to extract name & title...like "Beatles - Let It Be"
<?php
$url = "https://nostalgicfm.ro/NowOnAir.xml";
$xml = simplexml_load_file($url);
print_r($xml);
?>
Result is an Oject:
SimpleXMLElement Object ( [#attributes] => Array ( [System] => Jazler ) [Event] => SimpleXMLElement Object ( [#attributes] => Array ( [status] => happening [startTime] => 20:51:21 [eventType] => song ) [Announcement] => SimpleXMLElement Object ( [#attributes] => Array ( [Display] => ) ) [Song] => SimpleXMLElement Object ( [#attributes] => Array ( [title] => If You Were A Sailboat ) [Artist] => SimpleXMLElement Object ( [#attributes] => Array ( [name] => Katie Melua ) [Media] => SimpleXMLElement Object ( [#attributes] => Array ( [runTime] => 228.732 ) ) [Expire] => SimpleXMLElement Object ( [#attributes] => Array ( [Time] => 20:55:09 ) ) ) ) ) )
Resolved it myself:
<?php
$url = 'https://nostalgicfm.ro/NowOnAir.xml';
$xml = simplexml_load_file($url);
foreach ( $xml->Event->Song->Artist->attributes() as $tag => $value );
foreach ( $xml->Event->Song->attributes() as $tag => $value1 ) {
echo $value." - ".$value1.PHP_EOL; }
?>
I am trying to iterate over set of nodes given by xpath and set certain attribute for each node. However it works only for nodes withou content or with empty (whitespace) content. I have tried 2 approaches but with the same result (maybe they are both the same on some deeper level, dunno). The commented line is the second approach.
$temp = simplexml_load_string (
'<toolbox>
<hammer/>
<screwdriver> </screwdriver>
<knife>
sharp
</knife>
</toolbox>' );
echo "vanilla toolbox: ";
print_r($temp);
$nodes = $temp->xpath('//*[not(#id)]');
foreach($nodes as $obj) {
$tempdom = dom_import_simplexml($obj);
$tempdom->setAttributeNode(new DOMAttr('id', 5));
//$obj->addAttribute('bagr', 5);
}
echo "processed toolbox: ";
print_r($temp);
This is output. Attribute id is missing in node knife.:
vanilla toolbox: SimpleXMLElement Object
(
[hammer] => SimpleXMLElement Object
(
)
[screwdriver] => SimpleXMLElement Object
(
[0] =>
)
[knife] =>
sharp
)
processed toolbox: SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => 5
)
[hammer] => SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => 5
)
)
[screwdriver] => SimpleXMLElement Object
(
[#attributes] => Array
(
[id] => 5
)
[0] =>
)
[knife] =>
sharp
I'm unable to reproduce what you describe, the changed XML is:
<?xml version="1.0"?>
<toolbox id="5">
<hammer id="5"/>
<screwdriver id="5"> </screwdriver>
<knife id="5">
sharp
</knife>
</toolbox>
Demo
It's exactly your code, maybe you're using a different LIBXML version? See the LIBXML_VERSION constant (codepad viper has 20626 (2.6.26)).
But probably it's just only the print_r output for a SimpleXMLElement object.
It does not output the attributes for the last element, even on a brand new object, but it's still possible to access the attribute. Demo.
You will see when you print_r($temp->knife['id']); that the attribute is set (as you can see in the earlier XML output).