PHP Xml Attribute Parsing - php

I am Parsing XML currently using:
$data = simplexml_load_string($xmlFile);
foreach($data->item as $key => $current){
echo($current);
}
However I'm wondering, if a hit an element that looks like this:
<thumbnail url="http://foo.bar" height="225" width="300"/>
How do i pull the inner parts of this? (height, url, width)
Thanks!

foreach($data->item->thumbnail as $thumbnail) {
$url = $thumbnail['url'];
$height = $thumbnail['height'];
$width = $thumbnail['width'];
}

In case you don't know how many attributes there will be...
foreach ($data->item->thumbnail->attributes() as $key => $value) {
$attr[$key] = (string)$value;
}

Related

How to check if namespace element exists in PHP

I'm trying to check if the element media:content exists so that a thumbnail image can be shown from an rss feed but not sure how to validate it's existence.
I can get the media:content url and show the image fine but checking to see if it exists isn't working out. I've tried isset and defined but I'm clearly doing something wrong.
Main line i'm concerned about below is:
if(defined($item->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'content')->item(0)->getAttribute('url')))
<?php
$feed = new DOMDocument();
$feed->load('http://rss.cnn.com/rss/cnn_topstories.rss');
$json = array();
$items = $feed->getElementsByTagName('channel')->item(0)->getElementsByTagName('item');
$json['item'] = array();
foreach($items as $item) {
$title = $item->getElementsByTagName('title')->item(0)->firstChild->nodeValue;
$description = $item->getElementsByTagName('description')->item(0)->firstChild->nodeValue;
$text = $item->getElementsByTagName('description')->item(0)->firstChild->nodeValue;
if(defined($item->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'content')->item(0)->getAttribute('url'))){
$image = $item->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'content')->item(0)->getAttribute('url');
}
else{
$image = '';
}
echo $image;
}
?>
When you use getElementsByTagName, this always returns a DOMNodeList. The main thing is to check if the node list has 0 elements.
So rather than defined() or isset(), use ->length...
$nodes=$domDocument->getElementsByTagName('book') ;
if ($nodes->length==0) {
// no results
}
( Example from http://php.net/manual/en/domdocument.getelementsbytagname.php)
Nigel was right, using ->length is the way to do it.
if($item->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'content')->length > 0){
$image = $item->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'content')->item(0)->getAttribute('url');
}

PHP - Get random image from xml file

I want to display a random image from the Unsplash.com RSS feed (https://unsplash.com/rss) using PHP. I've read about how to this, but I can't seem to quite understand it. I think the easiest way to do this is would be with SimpleXML. Then I'd like to use the image as a background-image for my website. Can anyone help me out with this? Thanks!
Try this :
function getRandomImageFromRSS($url = 'https://unsplash.com/rss')
{
$xml = simplexml_load_file($url);
$images = array();
foreach ($xml->channel->item as $item)
{
foreach ($item->image->url as $url)
{
$images[] = (string) $url;
}
}
shuffle($images);
return isset($images[0]) ? $images[0] : null;
}
echo getRandomImageFromRSS();

PHP DOMDocument parentNode->replaceChild causing foreach to skip next item

I am parsing html in the $content variable with the DOMDocument to replace all iframes with images. The foreach is only replacing the ODD iframes. I have removed all the code in the foreach and found the piece of code causing this is: '$iframe->parentNode->replaceChild($link, $iframe);'
Why would the foreach be skipping all of the odd iframes?
The code:
$count = 1;
$dom = new DOMDocument;
$dom->loadHTML($content);
$iframes = $dom->getElementsByTagName('iframe');
foreach ($iframes as $iframe) {
$src = $iframe->getAttribute('src');
$width = $iframe->getAttribute('width');
$height = $iframe->getAttribute('height');
$link = $dom->createElement('img');
$link->setAttribute('class', 'iframe-'.self::return_video_type($iframe->getAttribute('src')).' iframe-'.$count.' iframe-ondemand-placeholderImg');
$link->setAttribute('src', $placeholder_image);
$link->setAttribute('height', $height);
$link->setAttribute('width', $width);
$link->setAttribute('data-iframe-src', $src);
$iframe->parentNode->replaceChild($link, $iframe);
echo "here:".$count;
$count++;
}
$content = $dom->saveHTML();
return $content;
This is the problem line of code
$iframe->parentNode->replaceChild($link, $iframe);
A DOMNodeList, such as that returned from getElementsByTagName, is "live":
that is, changes to the underlying document structure are reflected in all relevant NodeList... objects
So when you remove the element (in this case by replacing it with another one) it no longer exists in the node list, and the next one in line takes its position in the index. Then when foreach hits the next iteration, and hence the next index, one will be effectively skipped.
Don't remove elements from the DOM via foreach like this.
An approach that works instead would be to use a while loop to iterate and replace until your $iframes node list is empty.
Example:
while ($iframes->length) {
$iframe = $iframes->item(0);
$src = $iframe->getAttribute('src');
$width = $iframe->getAttribute('width');
$height = $iframe->getAttribute('height');
$link = $dom->createElement('img');
$link->setAttribute('class', 'iframe-'.self::return_video_type($iframe->getAttribute('src')).' iframe-'.$count.' iframe-ondemand-placeholderImg');
$link->setAttribute('src', $placeholder_image);
$link->setAttribute('height', $height);
$link->setAttribute('width', $width);
$link->setAttribute('data-iframe-src', $src);
$iframe->parentNode->replaceChild($link, $iframe);
echo "here:".$count;
$count++;
}
Faced this issue today, and guide by the answer, i make a simple code solution for you guys
$iframes = $dom->getElementsByTagName('iframe');
for ($i=0; $i< $iframes->length; $i++) {
$iframe = $iframes->item($i);
if("condition to replace"){
// do some replace thing
$i--;
}
}
Hope this help.

Fetch images URL from XML

I am using the below code to fetch the $movie->id from the response XML
<?php
$movie_name='Dabangg 2';
$url ='http://api.themoviedb.org/2.1/Movie.search/en/xml/accd3ddbbae37c0315fb5c8e19b815a5/%22Dabangg%202%22';
$xml = simplexml_load_file($url);
$movies = $xml->movies->movie;
foreach ($movies as $movie){
$arrMovie_id = $movie->id;
}
?>
the response xml structure is
How to fetch image URL with thumb size?
See the below an easy way to get only specific images.
$xml = simplexml_load_file($url);
$images = $xml->xpath("//image");
//echo "<pre>";print_r($images);die;
foreach ($images as $image){
if($image['size'] == "thumb"){
echo "URL:".$image['url']."<br/>";
echo "SIZE:".$image['size']."<br/>";
echo "<hr/>";
}
}
Use the attributes() method of SimpleXmlElement.
Example:
$imageAttributes = $movie->images[0]->attributes();
$size = $imageAttributes['size'];
See the documentation at: http://www.php.net/manual/en/simplexmlelement.attributes.php
EDIT: select only URL attributes with size = "thumb" and type = "poster":
$urls = $xml->xpath("//image[#size='thumb' and #type='poster']/#url");
if you expect only 1 url, do:
$url = (string)$xml->xpath("//image[#size='thumb' and #type='poster']/#url")[0];
echo $url;
working live demo: http://codepad.viper-7.com/wdmEay

having problems passing array values

I'm building a PHP program that basically grabs only image links from my twitter feed and displays them on a page, I have 3 components that I have set up that all work fine on their own.
The first component is the twitter oauth component which grabs the tweet text and creates an array, this works fine by itself.
The second is a function that processes the tweets and only returns tweets that contain image links, this as well works fine.
The program breaks down during the third section when the links are processed and an image is displayed, I had no issues running this on its own and from my attempts to trouble shoot it appears that it breaks down at the $images(); array, as that array is empty.
I'm sure I've made a silly mistake but I've been trying to find this for over a day now and can't seem to fix it. Any help would be great! Thanks guys!
code:
<?php
if ($result['socialorigin']== "twitter"){
$twitterObj = new EpiTwitter($consumer_key, $consumer_secret);
$token = $twitterObj->getAccessToken();
$twitterObj->setToken($result['oauthtoken'], $result['oauthsecret']);
$tweets = $twitterObj->get('/statuses/home_timeline.json',array('count'=>'200'));
$all_tweets = array();
$hosts = "lockerz|yfrog|twitpic|tumblr|mypict|ow.ly|instagr";
foreach($tweets as $tweet) {
$twtext = $tweet->text;
if(preg_match("~http://($hosts)~", $twtext)){
preg_match_all("#(^|[\n ])([\w]+?://[\w]+[^ \"\n\r\t<]*)#ise", $twtext, $matches, PREG_PATTERN_ORDER);
foreach($matches[0] as $key2 => $link){
array_push($all_tweets,"$link");
}
}
}
function height_compare($a1, $b1)
{
if ($a1 == $b1) {
return 0;
}
return ($a1 > $b1) ? -1 : 1;
}
foreach($all_tweets as $alltweet => $tlink){
$doc = new DOMDocument();
// Okay this is HTML is kind of screwy
// So we're going to supress errors
#$doc->loadHTMLFile($tlink);
// Get all images
$images_list = $doc->getElementsByTagName('img');
$images = array();
foreach($images_list as $image) {
// Get the src attribute
$image_source = $image->getAttribute('src');
if (substr($image_source,0,7)=="http://"){
$image_size_info = getimagesize($image_source);
$images[$image_source] = $image_size_info[1];
}
}
// Do a numeric sort on the height
uasort($images, "height_compare");
$tallest_image = array_slice($images, 0,1);
$mainimg = key($tallest_image);
echo "<img src='$mainimg' />";
}
print_r($all_tweets);
print_r($images);
}
Change the for loop where you fetch the actual images to move the images array OUTSIDE the for loop. This will prevent the loop from clearing it each time through.
$images = array();
foreach($all_tweets as $alltweet => $tlink){
$doc = new DOMDocument();
// Okay this is HTML is kind of screwy
// So we're going to supress errors
#$doc->loadHTMLFile($tlink);
// Get all images
$images_list = $doc->getElementsByTagName('img');
foreach($images_list as $image) {
// Get the src attribute
$image_source = $image->getAttribute('src');
if (substr($image_source,0,7)=="http://"){
$image_size_info = getimagesize($image_source);
$images[$image_source] = $image_size_info[1];
}
}
// Do a numeric sort on the height
uasort($images, "height_compare");
$tallest_image = array_slice($images, 0,1);
$mainimg = key($tallest_image);
echo "<img src='$mainimg' />";
}

Categories