how to access this child element - attribute in php simplexml - php

I want to access the 'url' attribute in the media:content element below. I am pretty sure this gives me the media:content, but I can not seem to get the url (see what I tried below):
$theContent = $item->children('media', true)->content;
xml:
<item>
<media:content type="image/jpeg" url="my url" />
</item>
I have tried variations:
$theURL = $item->children('media', true)->content['url'];
and
$mediaItem=$item->children('media', true)->content;
$contentItem=$mediaItem->children('content', true);
$url = $contentItem['url'];
No luck. ??

Complete working code with output:
<?php
$xml = '<item>
<media:content type="image/jpeg" url="my url" />
</item>';
$theContent = #new SimpleXMLElement($xml);
$attributes = $theContent->content->attributes();
echo $attributes['url']; //outputs: my url
?>
References: SimpleXML Attributes

Related

How to parse <media:content> tag in RSS with simplexml

Structure of my RSS from http://rss.cnn.com/rss/edition.rss is:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?>
<?xml-stylesheet type="text/css" media="screen" href="http://rss.cnn.com/~d/styles/itemcontent.css"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<title><![CDATA[CNN.com - RSS Channel - Intl Homepage - News]]></title>
<description><![CDATA[CNN.com delivers up-to-the-minute news and information on the latest top stories, weather, entertainment, politics and more.]]></description>
<link>http://www.cnn.com/intl_index.html</link>
...
<item>
<title><![CDATA[Russia responds to claims it has damaging material on Trump]]></title>
<description><![CDATA[The Kremlin denied it has compromising information about US President-elect Donald Trump, describing the allegations as "pulp fiction".]]></description>
<link>http://www.cnn.com/2017/01/11/politics/russia-rejects-trump-allegations/index.html</link>
<guid isPermaLink="true">http://www.cnn.com/2017/01/11/politics/russia-rejects-trump-allegations/index.html</guid>
<pubDate>Wed, 11 Jan 2017 14:44:49 GMT</pubDate>
<media:group>
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-super-169.jpg" height="619" width="1100" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-large-11.jpg" height="300" width="300" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-vertical-large-gallery.jpg" height="552" width="414" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-video-synd-2.jpg" height="480" width="640" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-live-video.jpg" height="324" width="576" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-t1-main.jpg" height="250" width="250" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-vertical-gallery.jpg" height="360" width="270" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-story-body.jpg" height="169" width="300" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-t1-main.jpg" height="250" width="250" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-assign.jpg" height="186" width="248" />
<media:content medium="image" url="http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-hp-video.jpg" height="144" width="256" />
</media:group>
</item>
...
</channel>
</rss>
If you parse this XML with simplexml like this:
$rss = simplexml_load_file($url, null, LIBXML_NOCDATA);
$rssjson = json_encode($rss);
$rssarray = json_decode($rssjson, TRUE);
you will see that <media:content> is simply missing in $rssarray items. So I found a tutorial with "namespace" solution. However, in the example author is using:
foreach ($xml->channel->item as $item) { ... }
but I am using (cannot use foreach for some reasons):
$rssjson = json_encode($rss);
$rssarray = json_decode($rssjson, TRUE);
So I modified the solution for my case like this:
$rss = simplexml_load_file($url, null, LIBXML_NOCDATA);
$namespaces = $rss->getNamespaces(true); // get namespaces
$rssjson = json_encode($rss);
$rssarray = json_decode($rssjson, TRUE);
if (isset($rssarray['channel']['item'])) {
foreach ($rssarray['channel']['item'] as $key => $item) {
$media_content = $rss->channel->item[$key]->children($namespaces['media']);
foreach($media_content as $tag) {
$tagjson = json_encode($tag);
$tagarray = json_decode($tagjson, TRUE);
}
}
}
But it does not work. For every item I get in $tagarray as a result an array with this structure:
Array(
'content' => array(
'0' => array(null),
'1' => array(null),
...
'11' => array(null),
)
)
It is an array with as many items as is the count of <media:content> tags, but every item is empty. I need to get an url attribute of every item. What am I doing wrong and getting an empty array?
Tags are actually empty:
<media:content ... />
^^
Information is contained in attributes, which can be fetched with SimpleXMLElement::attributes(), e.g.:
$rss = simplexml_load_file($url, null, LIBXML_NOCDATA);
$namespaces = $rss->getNamespaces(true);
$media_content = $rss->channel->item[0]->children($namespaces['media']);
foreach($media_content->group->content as $i){
var_dump((string)$i->attributes()->url);
}
I suspect the problem comes from the JSON trick. SimpleXML generates all its classes and properties dynamically (they aren't regular PHP classes), what means that you can't fully rely on standard PHP features like print_r() or json_encode(). This gets illustrated if you insert this in the above loop:
var_dump($i, json_encode($i), (string)$i->attributes()->url);
object(SimpleXMLElement)#2 (0) {
}
string(2) "{}"
string(91) "http://i2.cdn.turner.com/cnnnext/dam/assets/161115120658-trump-putin-t1-tease-super-169.jpg"
...
I had requirement to aggregate RSS news feeds from different source which had images tags in different formats so I used below code:
//Sample Feed 1: https://www.hindustantimes.com/rss/topnews/rssfeed.xml
//Sample Feed 2: https://economictimes.indiatimes.com/rssfeedsdefault.cms
$feed=$_GET['feed'];
$rss = simplexml_load_file($feed);
$namespaces = $rss->getNamespaces(true);
echo '<strong>'. $rss->channel->title . '</strong><br><br>';
foreach ($rss->channel->item as $item) {
$media_content = $item->children($namespaces['media']);
foreach($media_content as $i){
$imageAlt = (string)$i->attributes()->url;
}
echo "Link: " . $item->link ."<br>";
echo "Title: " . $item->title ."<br>";
echo "Description: " . $item->description ."<br>";
echo "PubDate: " . $item->pubDate ."<br>";
echo "Image: " . $item->image ."<br>";
echo "ImageAlt: " . $imageAlt ."<br>";
echo "<br><br>";
}

How to get first image from a tumlbr rss feed in PHP

0Here is the relevant part of my rss feed:
<channel>
<description></description>
<title>Untitled</title>
<generator>Tumblr (3.0; #xxx)</generator>
<link>http://xxx.tumblr.com/</link>
<item>
<title>Title</title>
<description><figure><img src="https://31.media.tumblr.com/c78c7t3abd23423549d3bb0f705/tumblr_inline_nkp9z234d0uj.jpg"/></figure></description>
<link>http://xxx.tumblr.com/post/99569244093</link>
<guid>http://xxx.tumblr.com/post/99569244093</guid>
<pubDate>Thu, 09 Oct 2014 11:19:33 -0400</pubDate>
</item>
</channel>
Using the answer from other questions on here I tried this:
$content = file_get_contents("http://xxx.tumblr.com/rss");
$feed = new SimpleXmlElement($content);
$imgs = $feed->channel->item[0]->description->xpath('//img');
foreach($imgs as $image) {
echo (string)$image['src'];
};
This is returning an empty array for $imgs
Does it have something to do with the tags being < > etc?
and if so what can I do?
You can get it from the description, which seems to include a HTML image tag for the image, by using a simple regular expression with preg_match:
$content = file_get_contents("http://xxx.tumblr.com/rss");
$feed = new SimpleXmlElement($content);
$img = (string)$feed->channel->item[0]->description;
if (preg_match('/src="(.*?)"/', $img, $matches)) {
$src = $matches[1];
echo "src = $src", PHP_EOL;
}
Output:
src = http://40.media.tumblr.com/58d24c3009638514325b113859ba369f/tumblr_nk0mwfhKXU1sl87kjo1_500.jpg
Before you can use xapth() on the description, you need to create a new XML document out of it:
$url = "http://xxx.tumblr.com/rss";
$desc = simplexml_load_file($url)->xpath('//item/description[1]')[0];
$src = simplexml_load_string("<x>$desc</x>")->xpath('//img/#src')[0];
echo $src;
Output:
http://40.media.tumblr.com/58d24c3009638514325b113859ba369f/tumblr_nk0mwfhKXU1sl87kjo1_500.jpg
I'm not sure if you can use this approach - as already mentioned by kjhughes as comment, your input XML does not contain any img element. But it's possible to retrieve the image source using XPath substring-functions:
substring-before(substring-after(substring-after(//item/description[contains(.,'img')],
'src='),'"'),'"')
Result:
https://31.media.tumblr.com/c78c7t3abd23423549d3bb0f705/tumblr_inline_nkp9z234d0uj.jpg

PHP With Youtube XML API

My problem is regarding using PHP to access data from a YouTube XML feed. The truncated feed is like this:
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">
<id>http://gdata.youtube.com/feeds/api/users/AaiKcIfHEzUZl34U980sNA</id>
<yt:firstName>wahbanana</yt:firstName>
<yt:googlePlusUserId>118419787126790739507</yt:googlePlusUserId>
<yt:location>SG</yt:location>
<yt:statistics lastWebAccess="1970-01-01T00:00:00.000Z" subscriberCount="353936" videoWatchCount="0" viewCount="0" totalUploadViews="40288085" />
<media:thumbnail url="http://yt3.ggpht.com/-ukikCGaaWTw/AAAAAAAAAAI/AAAAAAAAAAA/zmPZoDtJEK0/s88-c-k-no/photo.jpg" />
<yt:username>wahbanana</yt:username>
</entry>
I wrote a function to get subscribeCount iinside yt:statistics:
$url = 'http://gdata.youtube.com/feeds/api/users/'.$yt_username;
$xml = file_get_contents($url);
$feed = simplexml_load_string($xml);
$ns=$feed->getNameSpaces(true);
$yt = $entry->children($ns['yt']);
$yt_statistics = $yt->statistics->attributes();
$yt_subscribers = $yt_statistics['subscriberCount'];
But it returns this error:
PHP Fatal error: Call to a member function children() on a non-object in /home/digitali/public_html/wp-content/plugins/OCG-socialintegration/ocg_si.php on line 111
Can someone point out to me what is wrong? Thanks!
you dont have $entry, change to:
$feed = simplexml_load_string($xml);
$ns = $feed->getNamespaces(true);
$yt = $feed->children($ns['yt']);
.....

update node values of a XML with multiple child nodes from php

Following is my XML file i want to update the doller and cent values which are inside latestBid. I first tried the doller values but it's not working. i even tried to update the description ('//item[id="4"]/description') even that didn't work. Please tell me what i'm doing wrong here.
XML file
<?xml version="1.0"?>
<items>
<item>
<itemNumber>4</itemNumber>
<latestBid>
<latestCustomerId>1</latestCustomerId>
<bidPrice>
<doller>2342</doller>
<cent>23</cent>
</bidPrice>
</latestBid>
</item>
<item>
<itemNumber>5</itemNumber>
<latestBid>
<latestCustomerId>1</latestCustomerId>
<bidPrice>
<doller>35345</doller>
<cent>78</cent>
</bidPrice>
</latestBid>
</item>
</items>
PHP file
<?php
$url = '../../data/auction2.xml';
$itemNumber ="4";
$bidDoller = 45;
$bidCent=55;
$doc = new DomDocument();
$xml=simplexml_load_file($url);
//echo "came 1";working
foreach ($xml->xpath('//item[#itemNumber="4"]/latestBid/bidPrice/doller') as $desc) {
echo "came 2";//nt working
$dom=dom_import_simplexml($desc);
$dom->nodeValue = $bidDoller;
}
file_put_contents($url, $xml->asXML());
?>
edited. Still not working
thank you every one for the support by editing and answering I finally did it. since it wasn't easy for me to do this i'm posting the answer to help someone like me :).
i didn't change the xml.
php file
$url = '../../data/auction2.xml';
$itemNumber ="4";
$bidDoller = 85;
$bidCent=95;
$xml=simplexml_load_file($url);
$resultDoller= $xml->xpath('//item[itemNumber="'.$itemNumber.'"]/latestBid/bidPrice/doller');
$resultCent= $xml->xpath('//item[itemNumber="'.$itemNumber.'"]/latestBid/bidPrice/cent');
$resultDoller[0][0]=$bidDoller;
$resultCent[0][0]=$bidCent;
print $xml->asXML();
file_put_contents($url, $xml->asXML());
Following worked for me,
//XML
<?xml version="1.0"?>
<items>
<item id="4">
<itemNumber>4</itemNumber>
<latestBid>
<latestCustomerId>1</latestCustomerId>
<bidPrice>
<doller>2342</doller>
<cent>23</cent>
</bidPrice>
</latestBid>
</item>
<item>
<itemNumber>5</itemNumber>
<latestBid>
<latestCustomerId>1</latestCustomerId>
<bidPrice>
<doller>35345</doller>
<cent>78</cent>
</bidPrice>
</latestBid>
</item>
</items>
//PHP
<?php
$url = '../../data/auction2.xml';
$itemNumber ="4";
$bidDoller = 45;
$bidCent=55;
$doc = new DomDocument();
$xml=simplexml_load_file($url);
$result = $xml->xpath('//item[#id="4"]/latestBid/bidPrice/doller');
echo "<pre>";
print_r($result);
//echo "came 1";working
foreach ($xml->xpath('//item[#id="4"]/latestBid') as $desc) {
echo "came 2";//nt working
$dom=dom_import_simplexml($desc);
$dom->nodeValue = $bidDoller;
}
//file_put_contents($url, $xml->asXML());
?>

Pull XML nodeValue into php Variable

I am trying to assign the <all> / <avg> value in this XML code to a variable, so that I can use it for calculations. But when I do this, and try to print the value, I get a blank screen. Can someone please help?
<stats>
<type id="a">
<buy>
<volume>698299009</volume>
<avg>17.94</avg>
<max>18.45</max>
<min>1.00</min>
</buy>
<sell>
<volume>16375234</volume>
<avg>21.03</avg>
<max>24.99</max>
<min>20.78</min>
</sell>
<all>
<volume>714674243</volume>
<avg>18.01</avg>
<max>24.99</max>
<min>1.00</min>
</all>
</type>
</stats>
The php code I am using is as follows:
$xml = simplexml_load_file("values.xml");
$unit_value = $xml->xpath("/stats/type[#id='a']/buy/avg/")->nodeValue;
echo $unit_value;
Please refer documentation here, $xml->xpath should return you the array. The docs also shows an example of how to access text nodes. Below is an excerpt from the docs
<?php
$string = <<<XML
<a>
<b>
<c>text</c>
<c>stuff</c>
</b>
<d>
<c>code</c>
</d>
</a>
XML;
$xml = new SimpleXMLElement($string);
/* Search for <a><b><c> */
$result = $xml->xpath('/a/b/c');
while(list( , $node) = each($result)) {
echo '/a/b/c: ',$node,"\n";
}
/* Relative paths also work... */
$result = $xml->xpath('b/c');
while(list( , $node) = each($result)) {
echo 'b/c: ',$node,"\n";
}
?>
which produces output as
/a/b/c: text
/a/b/c: stuff
b/c: text
b/c: stuff
which is I suppose exactly what you need.
xpath returns an array of SimpleXMLElement objects .. so you can do this :
$unit_value = $xml->xpath("//stats//type[#id='a']//buy//avg");
echo (string)$unit_value[0]; // cast to string not required
Working example here
or if you are using PHP => 5.4 you can do this :
$unit_value = $xml->xpath("//stats//type[#id='a']//buy//avg")[0];
echo $unit_value;
Working example here

Categories