PHP SimpleXml - Retrieving attributes of namespaced children - php

I'm parsing an external Atom feed, some entries have a collection of namespaced children - I'm failing to retrieve attributes from those children. Abbreviated example:
$feed = <<<EOD
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:ai="http://activeinterface.com/thincms/2012">
<entry>
<title>Some Title</title>
<ai:image>path/to/some/image</ai:image>
<ai:ocurrence dateid="20120622" date="Fri, June 22, 2012" time="6:00 pm" />
<ai:ocurrence dateid="20120720" date="Fri, July 20, 2012" time="6:00 pm" />
</entry>
</feed>
EOD;
$xml = new SimpleXmlElement($feed);
foreach ($xml->entry as $entry){
echo $entry->title;
$namespaces = $entry->getNameSpaces(true);
$ai = $entry->children($namespaces['ai']);
echo $ai->image;
foreach($ai->ocurrence as $o){
echo $o['date'];
}
}
Everything but the attribute retrieval of the namespaced children works fine - if the children's tagnames aren't namespaced, it works fine. If grabbing the node value (rather than an attribute), even if namespaced, it works fine. What am I missing?

Try this
$xml = new SimpleXmlElement($feed);
foreach ($xml->entry as $entry)
{
$namespaces = $entry->getNameSpaces(true);
$ai = $entry->children($namespaces['ai']);
foreach ($ai->ocurrence as $o)
{
$date=$o->attributes();
echo $date['date'];
echo "<br/>";
}
}

don't know why, but apparently array access won't work here... need the attributes method:
echo $o->attributes()->date;

Related

How to retrieve an attribute from a namespaced element

I am trying to get the url attributes from the <media:content> elements in this RSS feed:
https://news.google.com/rss/search?q=test&as_qdr=w1&scoring=n&num=100&hl=en-CA&gl=CA&ceid=CA:en
Here's what I have so far:
$feed_url = "https://news.google.com/rss/search?q=test&as_qdr=w1&scoring=n&num=100&hl=en-CA&gl=CA&ceid=CA:en";
$rss = file_get_contents($feed_url);
$rss = new SimpleXMLElement($rss);
$items = $rss->channel->item;
foreach ($items as $item) {
print_r($item);
echo "<hr>";
}
This code works for all elements except the ones with a semicolon in the name, like <media:content> or <dc:contributor>. If I open the XML feed in my browser I can see the tag I am looking for:
<media:content url="https://lh6.googleusercontent.com/proxy/nxX8kqpFKSDvYg_bf_QrdsS0PYNMFPGspYmTlZlIo0IzyyhYhURxQc5nrpnzfrNBZkWQywioGXdPclazSIEwiz5wklsBePHOCft9qdHl2EmqIES_SMl5orim2xM2eHYalvIgFFeGYvp7cQaCQpKAObhPGQ--diqZg4Io3MSW8f6PXlRAbUcPvpDxB-KRqBj53bbROhoUYuqxkA=-w150-h150-c" medium="image" width="150" height="150"/>
</item>
I tried various solutions from other threads but it didn't work for me. Example:
$xml_object = $rss->channel->item[0];
$ns_media = $xml_object->children('http://search.yahoo.com/mrss/');
I don't know what I'm doing wrong so I would appreciate some help
You're missing a call to the attributes() method of your SimpleXMLElement instance:
foreach ($items as $item) {
$media_content_url = $item->children('http://search.yahoo.com/mrss/')->attributes()->url;
// ...
}
I'm not familiar with SimpleXML, but this is simple enough to do with DomDocument:
$feed_url = "https://news.google.com/rss/search?q=test&as_qdr=w1&scoring=n&num=100&hl=en-CA&gl=CA&ceid=CA:en";
$rss = file_get_contents($feed_url);
$dom = new DomDocument;
$dom->loadXML($rss);
$nodes = $dom->getElementsByTagNameNS("http://search.yahoo.com/mrss/", "content");
foreach ($nodes as $node) {
printf("%s\n", $node->getAttribute("url"));
}
Output:
https://lh6.googleusercontent.com/proxy/m7yanlDdWIjGc1XmsY6AHB5DqqJcgSe1Z7vs9DUC5NbD-FfQqJzEY8uIadNckLJFu7O6rcuh4W-CsXRg2vjr_KLOWhwNG5shhfdetcUkY5dMHa0uN1GBC5iY0svkP-Wxcm7JJ_kJMh6sctcvJ5Hfbb2Vor8KPlnYXUk_Y3jxYeCgmDBTqeRKwQ1pTMtWtJ_7fK5P5PSdKQKjUNnfVODZjHg_c4PwFWw3Cw=-w150-h150-c
https://lh3.googleusercontent.com/proxy/j7vDbXvscxGVLF8xo2DGkEgmgyQ9-u5vE0RWJjmAp84xOuy4v-Ff6cHADsLiC2Zd2KE7s04sCgtT_WNx4K5vxjDw_jbFRwQhlBgpL-YdXMgvDgakxzx8xWDO5bdpHaVssEGXgkxCnXnHXBRgb67vXeY6XnbgeEp7Fe5ohK1fpyk_hE3IYGyHdJnTxiH_=-w150-h150-c
https://lh6.googleusercontent.com/proxy/nxX8kqpFKSDvYg_bf_QrdsS0PYNMFPGspYmTlZlIo0IzyyhYhURxQc5nrpnzfrNBZkWQywioGXdPclazSIEwiz5wklsBePHOCft9qdHl2EmqIES_SMl5orim2xM2eHYalvIgFFeGYvp7cQaCQpKAObhPGQ--diqZg4Io3MSW8f6PXlRAbUcPvpDxB-KRqBj53bbROhoUYuqxkA=-w150-h150-c
https://lh3.googleusercontent.com/proxy/PbDyKTNQAyxkLNnyQFm00dHkNyKoASc3zKJjw7tjRtfmebHfbP_Ov_5RfcsG1RL8gyFaMSvVltd7IQJns6x_N_thPQTWz7E3ER0RlqLhZBYjmM-cp9xUkCdICiFyfkY0XGx-xGSh6zq5C_SpuzAxCVdhoOkqW4Lz_kyw-KN1fUJB6b8VgDGFvssIfmurSm3qCdJYeFJAx7x6lh_NQS1GNeNdbVBf0RoE2jiZfK6SYgFCX2s9KifQ7Sld_0plNrvTyW6VSR9D0AEwlBClWXNfoMmB_NYl4j03ELoUIjB0fRpUxV7YAqiIC1nSxqn92Q=-w150-h150-c
https://lh6.googleusercontent.com/proxy/DcJhP_BX_r7IbiwFgYt7MOL8RKQMizjCEWAn4YBcWdDy-PYOncpb_PrDZ0H5cMlxSFk9X8SQz5WEAX1xJRV4RWBiPwSH6uDJr7bt1Dh4H7MyYAaB_66BnASNA-fw0pszLPYEgfkwZsRyEZNT045MRYXA3Q=-w150-h150-c
https://lh5.googleusercontent.com/proxy/ECDRkzc4AO3OP1V0PNEVw1OhBYwuDRJVdDzF9lFNW34D8aNO8s54aWJfuR_LhDz-wKCRRvS64ggZnsg2UkCE5EYJghnBkQlpmwktgFYcKW0OnXP_-Ynh37EHR9nG9lyRoM1-3ebj=-w150-h150-c
https://lh6.googleusercontent.com/proxy/9xL1YVQyHg2mzitNgeiHRkjq_vJBxmOb0iAb1bBfJcqFLlWOJWkzRmLYrc9-hmK4nGcLnFfLMEb-bTnZmlWRM72_9ibysFUU_z-77ZK5PhX-f8vfIoWp=-w150-h150-c
https://lh5.googleusercontent.com/proxy/FcDG9_8xHTVUP2uHZ6cMAnIAdDxd-Kg29IksHUEDJCX8_mjTd2voG8BITnqpPEXKtFEImDogPfJfHNlqJr7X2I0VHlkesJvRnE2D-aLRxiNJfc2Lh6WIb0PrRy2nluPe6IJOhUulh0AzZ8JXJVBPgYnfeifItdhBsCTz7QtKGN4DbLZzDAVRL28mHNzaFBlCjCMGyhrbR3jmmlLWqj5K6lbfdoS0jxbLDKkNY8ywVq61rua1YHe-J6ZOY40ESL_0hf27KTgIJFSNq99yGX2sMw=-w150-h150-c
https://lh3.googleusercontent.com/proxy/ciJtTGr7RBlyJD2JGS-Ps4OUOcHxph6Csa1RCJOhcIjjqnjMHnqDzBU2MwEBoieNz37zmC69cPcoUi9696CfpMYh_cry5O6xmTT-1BnlyJhGMTeDR2mIbf3-3VEJ5YsNHmyozvClGvbR6_ZOaMgH0w3AWwf_bZppmqXp7Bul8rXDOkIDMeHrmKCpQcJff-lAbV7hnud3h0JH0--7zw5wCCOj57dNwIA=-w150-h150-c
https://lh5.googleusercontent.com/proxy/nyoQUYC-IPq8Td_GPYc60euyS5cgKwUk7ta1ISJl9wafgrGt1HkhVtPSpoO36KZl_8em4B9bBuP_OXmR0RZlGk1yLwcfAK42NknrGy5H0bLwJqouJ0sE0a21EwardDsVGe1XhGXETO92NfSG2Tikpl9pUFLiJEE-ySdL2d5CK9LA82P4DG6FM5eW=-w150-h150-c
https://lh3.googleusercontent.com/proxy/F2QF_T-xeBkwMyMljtdxwaXMQmNvyG9YCv2QmdBBSmNCe6okG7AIuElWuXXI45IjTA8fuyEZbeGEHBJdWIeyxcjiwapXjzAIxm1lxrmMdzLgJyD4C867KZtcTS1NTWyJebHY4u3gBQ2Z=-w150-h150-c
https://lh4.googleusercontent.com/proxy/rbbBxl7QWG4BBIlsvJUIfL3fr8j4f7L_LoRc3NvfWcNOGT7oX7U1_CpJ71oE04TD0Ax75WmDJrlBQNYPGcsQnOid874Z6P3nwNpdNtZlytX_6FlXqefr58IQ3fB-sivfI20EmQVnRfaBXUozjpHbjW225jeI1hxWc1U15MC_rMuJryLEC_CV4OLg=-w150-h150-c
https://lh5.googleusercontent.com/proxy/7TRaIMikpkiHsWKNenXItiKUUSnRhEl92XSOmDHl828VWobr_M8crMxMLvfG9BDbVc4SioxINBmDyDLhxyHiLlk_c_-6ocsm6ATjrUbWHuc-FTba=-w150-h150-c
https://lh5.googleusercontent.com/proxy/VDXcSNdIqLdhl6IFXyQlwOlzDlhPGaPTOWN0XMuX_DHozxXowzuQMWGAnFNIizgXavLZ5rVcw9rGl7NWTHMyRboJVqjzRRtoOs1GJCb0dylyUsHSt5qUSOZULdyBDPkW6HXVDHHyR40EeR4CS9nOX0M=-w150-h150-c
https://lh5.googleusercontent.com/proxy/YlbnCDloJxYZBVFhx-k2JZzYzFhcBA6DMAim5QTgNoyB4-Q_8DjgR2-JV73ARnUmpROHYfdZiKwfEUCdPB7tUSJ-uJuSRFgfQ_t8CV6rQ8zAXiIKOuoNO20AMArh5NXKr99nP_FoiOLf6mIEJw--URXUP0Tg4-i7bCXXdIPIvVpWNaDxKesNa1MRzIWkzHnYoGuy5QGL7byi32Y0ld8mHP2KFbXT2aga0f3S5rl-ikFkRxpaSxk0coE=-w150-h150-c
https://lh6.googleusercontent.com/proxy/XgDFopqdfCYmrzYi5NKRDYZYZgmJ2fyAn-9eN9QnXgmBezTviTAYV4ct07peVeZMerMND3ZwgZ-lK8Uv7B6FivV6LXqAJN4E7OVvtKYToSriuCRK4QOTuf6oFXG0KTetG-QJCoHZT77mWJtCGb0jG9tch59MJ0aWWZ1NA5X7wF4aMtoLSHkvAK2cuspI85CpPMj2ayu6wiG-0GT8fcAwRsVW64773g=-w150-h150-c
https://lh6.googleusercontent.com/proxy/WTq4Z72Acy7ykLcNmv9b_B2IQerfE4M7V00dxJ1o65IBz4OPyDzKkDBrVLAvqKdSjOHuTsHwTw5_UBINqKU3tFIOeEjCdsOs3yLkqG52YI-NGYvtw0EUohgu6Ps=-w150-h150-c
https://lh6.googleusercontent.com/proxy/uyiP15MOcfSPSHn6FU_LMK08w-0WiaDKQwC0e5rC67ZmdEqYqDYQDjHCkkH0UB0vxLRNpUw0jyz_YCvZ713hPuAeZM4xk7ZItIzNnkXRv_H-n8196YojFvVHZjbRYNZguxHtN7uAT1hxNvrRlRL-pdG9eiUs58rx_w=-w150-h150-c
https://lh4.googleusercontent.com/proxy/MBgkZaPJYX173801aVCotrRKb5pTCO3orWgu0cgsCuglj0bAQW7Za7HhaQUVk2NIUxg8MQz0qiizFGBTSZXdcUwpsmTPpz2rXYuZpqxgSAsxjZH4RUZW9P74EuM-_KzJQ7fKZx7sVK26kLxXr206i6DWH8LCCFa9utvSWevAS2OlYSYc17a09Z6Af5NJ7FoIJ6jxh1wnsuZhfwebq_4zQGDg4AF9XVrKayVrYExcBtx-kYqgjAqTiswm7YoO1yJGBUNkXh1aXC76C50WEOiYemdoXeygD1KIsRpExccCQZZ_NDjIgRMjBvPAGy-1Ue1xwCiXvgFu1P7AtZ2g0XA=-w150-h150-c
https://lh6.googleusercontent.com/proxy/9TiiPwVKm7hFE4kzBEeQ2nrwR8h3hjJ1KLMw6G5s-3_FzO0QorKfKYkubFvF-YDgMYyujUloeApsM00xuBWgQYJE4vRrcdXFoAik032DyRykwAYl7e87Qjqb2wnNMUpfmX1PTZo_OK6VC69sGQY9ISWevaI09tKI6w=-w150-h150-c
https://lh4.googleusercontent.com/proxy/bePdkudsqFAyihVJPg94KH4SKhVTwB0BSFiXEsCdQEZubli_o9RtbEctWtw1X5CC_x9JqM9vBPhWMyP29eBmkrCzi04osGEwiTOoaeLI3WhPl49w0UKeNvOONgkK3ZbPhJ4RFutptw71nhLoiWX2uAUDChy_zgxYmg=-w150-h150-c
https://lh5.googleusercontent.com/proxy/GgkEfaSJZU_ZrtKUpU3aqKBS-u1fUkz3wDJH7m3iPlFduw_C0yfprGaOGubYqxBdILL69inogeniN3zM83hh2EaBGS5wNJ8PfmSe1bUOy605NxMR19SPSgeLu0hGlrc_d16v-V1OtwxDt2SVDM382UQ=-w150-h150-c
https://lh3.googleusercontent.com/proxy/C04R8mKirMGoXC7SvbOwbMAh2BpjAUcqRhyFEoZhIg2bl55t5jgF6zLwXvAAe4O95ETW1fp1sIQSGgzCoxlFBp51LCEzyfvDiKkxt0LpYzHmNTeIxmGTlmBkRv4wRNGquW0ZBp1AWnjoqaGosgMWv0kQI6QTkgFTEI5tuhrLppr_0Xcfy4JNSqo8bSVxa_fb27Iih5Evf1RUSS6Umnc6wW3cHip0icT7QmfdebQs3LUvSUqHaaeDikc60NOQdZRX8tUcODic84RoOn41vM8NvBrZZuQgImC8GTPavaMTUIsEOK4QxSNUdxKduRcPpa0p=-w150-h150-c
https://lh4.googleusercontent.com/proxy/qpUSiYScbVAjAv63NKloqPadlLXD7xWo0eocfLMerlUozukyVTS4QWZYcJBPmkHuxJZCh85Zh1mEepVEeZH3JSMxQRrcE-4Apawmnw=-w150-h150-c
https://lh6.googleusercontent.com/proxy/CNvMvcbMHHckCXbyFXkRZnnuPr17TEzvspLGwIobu15dDsrlHt-3QKzi7kcHKvTpJZlCr2l-HhWOPBfJJzPRrd2gn734awWdE5jXRcqrnfly4bwnIPokO68_luWur73lg-k=-w150-h150-c
https://lh4.googleusercontent.com/proxy/eDks_caYi82LNyG2L2AMQENYCuL7LfaH5rhL-qT6QiVnb5r142EFLTe4u61mZf-1xE2UkJB9GfcUy4x5IfNOU-JCd78FMn--f1CldoEY9y7ouU5cdZ8=-w150-h150-c
https://lh6.googleusercontent.com/proxy/WsWb8Woo-ogEIuDkvaBpsxrizSDUwM_k6h9w1ma-d_i4f3c9Bpefe6llemcMlZNODP5hx_raBrZ6dlclfDXJpirHGgVuTFp3W_mCdrGWO1LCsQf6Nz3iyjgJIbFFv12K3rC9sy2sfV3kgpQRURxi50MwLLG4lUcDx8LIiHWk5bG-VR9IBpygAMPtL5LJoRN8fkg9Vh7RA-J8kkbDm8-xirGXhkYheENaly7yH3qpIo_3aBYrHzS1GsCULOfpjdEuw2OISw=-w150-h150-c

Get xml node full path in Php / SimpleXml

I need the full path of an xml node.
I saw the answer in this question but I wasn't able to use it.
Below the code I used on a php web tester with no success:
$xml = <<<EOF
<root>
<First>
<Martha>Text01</Martha>
<Lucy>Text02</Lucy>
<Bob>
<Jhon>Text03</Jhon>
</Bob>
<Frank>One</Frank>
<Jessy>Two</Jessy>
</First>
<Second>
<Mary>
<Jhon>Text04</Jhon>
<Frank>Text05</Frank>
<Jessy>Text06</Jessy>
</Mary>
</Second>
</root>
EOF;
$MyXml = new SimpleXMLElement($xml);
$Jhons = $MyXml->xpath('//Jhon');
foreach ($Jhons as $Jhon){
echo (string) $Jhon;
//No one of the following works
echo (string) $Jhon->xpath('./node()/path()');
echo (string) $Jhon->xpath('./path()');
echo (string) $Jhon->xpath('.path()');
echo (string) $Jhon->path();
echo '<br/> ';
}
I need: "/root/First/Bob/Jhon" and "/root/Second/Mary/Jhon"
You can use the much more powerful DOM (DOMDocument based in PHP) api to do this...
$MyXml = new SimpleXMLElement($xml);
$Jhons = $MyXml->xpath('//Jhon');
foreach ($Jhons as $Jhon){
$dom = dom_import_simplexml($Jhon);
echo $dom->getNodePath().PHP_EOL;
}
The dom_import_simplexml($Jhon) converts the node and then getNodePath() displays the path...
This gives ( for the example)
/root/First/Bob/Jhon
/root/Second/Mary/Jhon
Or if you just want to stick to SimpleXML, you can use the XPath axes ancestor-or-self to list the current node and each parent node...
$MyXml = new SimpleXMLElement($xml);
$Jhons = $MyXml->xpath('//Jhon');
foreach ($Jhons as $Jhon){
$parent = $Jhon->xpath("ancestor-or-self::*");
foreach ( $parent as $p ) {
echo "/".$p->getName();
}
echo PHP_EOL;
}

Read colon tags values XML PHP

I've already read those topics:
PHP library for parsing XML with a colons in tag names? and
Simple XML - Dealing With Colons In Nodes but i coundt implement those solutions.
<item>
<title> TITLE </title>
<itunes:author> AUTHOR </itunes:author>
<description> TEST </description>
<itunes:subtitle> TEST </itunes:subtitle>
<itunes:summary> TEST </itunes:summary>
<itunes:image href="yoyoyoyo.jpg"/>
<pubDate> YESTERDAY </pubDate>
<itunes:block>no</itunes:block>
<itunes:explicit>no</itunes:explicit>
<itunes:duration>99:99:99</itunes:duration>
<itunes:keywords>key, words</itunes:keywords>
</item>
I want to get only itunes:duration and itunes:image. Here is my code:
$result = simplexml_load_file("http://blablabla.com/feed.xml");
$items = $result->xpath("//item");
foreach ($items as $item) {
echo $item->title;
echo $item->pubDate;
}
I tried using children() method but when i try to print_r it it says that the node no longer exists.
You should use the children() on the $item element to get it's child-elements:
$str =<<< END
<item>
<title> TITLE </title>
<itunes:author> AUTHOR </itunes:author>
<description> TEST </description>
<itunes:subtitle> TEST </itunes:subtitle>
<itunes:summary> TEST </itunes:summary>
<itunes:image href="yoyoyoyo.jpg"/>
<pubDate> YESTERDAY </pubDate>
<itunes:block>no</itunes:block>
<itunes:explicit>no</itunes:explicit>
<itunes:duration>99:99:99</itunes:duration>
<itunes:keywords>key, words</itunes:keywords>
</item>
END;
$result = #simplexml_load_string($str);
$items = $result->xpath("//item");
foreach ($items as $item) {
echo $item->title . "\n";
echo $item->pubDate . "\n";
echo $item->children()->{'itunes:duration'} . "\n";
}
Output:
TITLE
YESTERDAY
99:99:99
Here goes my alternative solution if Dekel's dont work for someone.
Using method getNamespaces
$result = simplexml_load_file("http://blablabla.com/feed.xml");
$items = $result->xpath("//item");
foreach ($items as $item)
{
$itunesSpace = $item->getNameSpaces(true);
$nodes = $item->children($itunesSpace['itunes']);
//TEST
echo $nodes->subtitle
//99:99:99
echo $nodes->duration
//If you want the image Href
$imageAux = $nodes->image->attributes();
//yoyoyoyo.jpg
echo $imageAux['href'];
}

Better way of retrieving info from XML file using XPATH

I've got so far a very simple class named Menu.php which contains the following:
<?php
class Menu
{
private $_dom;
private $categoryItems;
function __construct()
{
if(file_exists('Menu.xml'))
{
$this->_dom = simplexml_load_file('Menu.xml');
}
}
public function retrieveMenu($category)
{
$products = $this->_dom->xpath('/menu/category[#name="'.$category.'"]');
return $products;
}
} // end of class Menu
Pretty rudimentary, I know, is just for testing purposes.
Now, I also have a XML file like the following:
<?xml version="1.0" encoding="UTF-8" ?>
<menu>
<category name="pizza">
<item name="Tomato and Cheese">
<type>Regular</type>
<available>true</available>
<size name="Small">
<price>5.50</price>
</size>
<size name="Large">
<price>9.75</price>
</size>
</item>
</category>
<category name="pizza">
<item name="Pepperoni">
<type>Regular</type>
<available>true</available>
<size name="Small">
<price>6.85</price>
</size>
<size name="Large">
<price>10.85</price>
</size>
</item>
</category>
Which goes on with multiple products. So, the idea is to access this file through the class,
and to achieve that I'm doing the following in my index.php:
<?php
require 'Menu.php';
$menu = new Menu();
$tests = $menu->retrieveMenu('pizza');
foreach($tests as $test) {
echo $test->attributes();
echo '<br />';
foreach($test->item as $item) {
echo $item->attributes();
echo '<br />';
echo $item->type;
echo '<br />';
echo $item->available;
echo '<br />';
foreach($item->size as $price) {
echo $price->attributes();
echo '<br />';
echo $price->price;
echo '<br />';
echo '<br />';
echo $price->price;
echo '<br />';*/
}
//echo $item->size->attributes();
echo '<br /><br /><br /><br />';
}
}
Which is given me back the results I'd expect:
>pizza
>Tomato and Cheese
>Regular
>true
>Small
>5.50
>Large
>9.75
Now, my question is: Since I'm using 3 nested for loops if I'm not wrong the complexity is n^3, which is pretty awful, the original XML contains lots of products, is there a better way of accessing it? Am I doing something wrong?
By the way, YES, I MUST USE XML and XPATH
Nothing wrong with the nested loops in this case. You access and output all the sub elements on a single resource. But yes it is possible with Xpath to fetch nodes from different levels into a list.
Xpath expressions can use | to combine several location paths. So its is actually three location paths and the expression returns all of the matching nodes:
name attribute nodes from all elements: //*/#name
child elements of item except size: //item/*[not(self::size)]
price child elements of item/size: //item/size/price
This example uses DOM:
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
$expression = '//*/#name|//item/*[not(self::size)]|//item/size/price';
foreach ($xpath->evaluate($expression) as $node) {
echo trim($node->nodeValue), "<br/>\n";
}
Output:
pizza<br/>
Tomato and Cheese<br/>
Regular<br/>
true<br/>
Small<br/>
5.50<br/>
Large<br/>
9.75<br/>
pizza<br/>
Pepperoni<br/>
Regular<br/>
true<br/>
Small<br/>
6.85<br/>
Large<br/>
10.85<br/>
A location path in Xpath works like a filter, the nodes are returned in an order depending on their position in the document.
It works with SimpleXML, too:
$element = simplexml_load_string($xml);
$expression = '//*/#name|//item/*[not(self::size)]|//item/size/price';
foreach ($element->xpath($expression) as $node) {
echo trim($node), "<br/>\n";
}
Demo: https://eval.in/156266

PHP xml array parsing data

Hey all i have this type of XML i am trying to get data from. This is just a snip of the large XML code:
<entry>
<id>http://www.google.com/calendar/feeds/[Letters/numbers here]group.calendar.google.com/public/basic/[Letters/numbers here]</id>
<published>2013-08-01T13:40:24.000Z</published>
<updated>2013-08-01T13:40:24.000Z</updated>
<title type='html'>[Title Here]</title>
<summary type='html'>When: Tue Sep 24, 2013 7am</summary>
<content type='html'>When: Tue Sep 24, 2013 7am
<br />Event Status: confirmed
</content>
<link rel='alternate' type='text/html' href='https://www.google.com/calendar/event?eid=[Letters/numbers here]' title='alternate'/>
<link rel='self' type='application/atom+xml' href='https://www.google.com/calendar/feeds/[Letters/numbers here]group.calendar.google.com/public/basic/[Letters/numbers here]'/>
<author>
<name>[email here]</name>
<email>[email here]</email>
</author>
</entry>
etc... etc....
Currently i can get both published and updated just fine by doing the following:
<?php
$url = strtolower($_GET['url']);
$doc = new DOMDocument();
$doc->load('http://www.google.com/calendar/feeds/[number/letters here].calendar.google.com/public/basic');
$entries = $doc->getElementsByTagName("entry");
foreach ($entries as $entry) {
$tmpPublished = $entry->getElementsByTagName("published");
$published = $tmpPublished->item(0)->nodeValue;
$tmpUpdated = $entry->getElementsByTagName("updated");
$updated = $tmpUpdated->item(0)->nodeValue;
}
?>
However i am unsure as to how to get the inner data from within the parent array - that being link in this case.
So i need to get
link->href
I would imagine it would be:
$tmpLink = $entry->getElementsByTagName("link");
$link = $tmpLink->item( 2 )->nodeValue;
Any help would be great!
you can use:
$links = $doc->getElementsByTagName("link");
foreach ($links as $link) {
$href = $link->getAttribute("href");
}
if you want to get href... hope that I understood what you wanted :)
You can do this with simplexml_load_string like following codes:
$entries = simplexml_load_string($string);
foreach ($entries as $entry) {
echo $entry->published;
echo $entry->updated;
foreach($entry->link as $link)
{
echo $link->attributes()->type;
echo $link->attributes()->rel;
}
}

Categories