How to display XML RSS feed by PHP - php

I have an assignment to display my XML RSS via PHP on a website, so far I have tried multiple things and all have failed. And I was unable to find the answer since most people do RSS feed by PHP from MySQL database to get a live feed of posts.
XML RSS
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>Treehouse front page</title>
<link>https://teamtreehouse.com/</link>
<description>Programming Tutorials</description>
<item>
<title>Code Academy</title>
<link>https://teamtreehouse.com/</link>
<description>Programming Tutorials</description>
</item>
</channel>
</rss>
How can I display this file via PHP?

Try to use the DOMDocument() class, for example:
$rss = new DOMDocument();
$rss->load("http://yoursite.com/rss/");
$feed = array();
foreach ($rss->getElementsByTagName('item') as $node) {
$item = array (
'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
'desc' => $node->getElementsByTagName('description')->item(0)->nodeValue,
'link' => $node->getElementsByTagName('link')->item(0)->nodeValue,
'date' => $node->getElementsByTagName('pubDate')->item(0)->nodeValue,
);
array_push($feed, $item);
}
This is a tip. I hope I have helped you.

Thank you very much for leading me onto the right track!
But that code would work for DOM file while mine was simplexml.
I used the following code to solve the problem
<?php
$rss = simplexml_load_file('rss.xml');
echo '<h4>'. $rss->channel->title . '</h4>';
foreach ($rss->channel->item as $item) {
echo '<h4>' . $item->title . "</h4>";
echo "<p>" . $item->title . "</p>";
echo "<p>" . $item->description . "</p>";
}
?>

Related

How do I get the child nodes of this RSS feed?

How can I get the contest logo and start date from this RSS feed? I can get the dc:modified child for example but always get a blank for anything from dc:dataset.
My code:
$feed_url = 'https://www.website.com/?call_custom_simple_rss=1&csrp_post_type=contest&csrp_posts_per_page=2&csrp_show_meta=1';
$feed = file_get_contents($feed_url);
$rss = simplexml_load_string($feed);
foreach($rss->channel->item as $entry) {
echo $entry->children("dc", true)->modified . "<br>";
echo $entry->children("dc", true)->dataset->contest_logo . "<br>";
echo $entry->children("dc", true)->dataset->start_date . "<br>";
}
The RSS feed:
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:wp="http://wordpress.org/export/1.2/" xmlns:excerpt="http://wordpress.org/export/1.2/excerpt/" version="2.0">
<channel>
<title>RSS Title</title>
<description>A website</description>
<lastBuildDate>Wed, 17 Feb 2021 15:03:03 +0000</lastBuildDate>
<item>
<title>
<![CDATA[ Photography Awards ]]>
</title>
<link>
<![CDATA[ /contests/photography-awards/ ]]>
</link>
<pubDate>Mon, 11 Jan 2021 13:52:27 -0600</pubDate>
<dc:identifier>619116</dc:identifier>
<dc:modified>2021-02-09 07:50:10</dc:modified>
<dc:created unix="1610373147">2021-01-11 13:52:27</dc:created>
<dc:dataset>
<contest_logo>
<![CDATA[ 619130 ]]>
</contest_logo>
<start_date>
<![CDATA[ 20210110 ]]>
</start_date>
</dc:dataset>
</item>
</channel>
</rss>
The contest_logo and start_date are in the empty namespace. You have to switch back. Additionally it is not good to reply on namespace prefixes defined in the document. Use the namespace URI (for example defined as mapping array in your code).
$rss = simplexml_load_string($feed);
$xmlns = [
'dc' => 'http://purl.org/dc/elements/1.1/'
];
foreach($rss->channel->item as $entry) {
echo $entry->children($xmlns['dc'])->modified . "<br>";
echo $entry->children($xmlns['dc'])->dataset->children('')->contest_logo . "<br>";
echo $entry->children($xmlns['dc'])->dataset->children('')->start_date . "<br>";
}
Output:
2021-02-09 07:50:10<br>
619130
<br>
20210110
<br>
In DOM you would register an alias on the Xpath processor and use it in the expressions. Here is a demo:
$document = new DOMDocument();
$document->loadXML($feed);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/');
foreach ($xpath->evaluate('/rss/channel/item') as $entry) {
echo $xpath->evaluate('string(dc:modified)', $entry). "<br>";
echo $xpath->evaluate('string(dc:dataset/contest_logo)', $entry). "<br>";
echo $xpath->evaluate('string(dc:dataset/start_date)', $entry). "<br>";
}
Another alternative - use xpath:
echo $rss->xpath('//dc:dataset/contest_logo')[0] . "\r\n";
echo $rss->xpath('//dc:modified')[0] . "\r\n";
echo $rss->xpath('//start_date')[0] . "\r\n";
Output:
619130
2021-02-09 07:50:10
20210110

How to parse YouTube XML with PHP, including namespace descriptions

Im trying to use PHP's SimpleXMLElement to parse a YouTube channel feed and include the description. I can do this easily to get the title and video url.
Here is what I have that can get the descriptions
$channel_id = 'UCtNjkMLQQOX251hjGqimx2w';
$yt_url = 'https://www.youtube.com/feeds/videos.xml?channel_id=';
$xml_str = file_get_contents($yt_url.$channel_id);
$xml = new SimpleXMLElement($xml_str);
$xml->registerXPathNamespace('prefix', 'http://www.w3.org/2005/Atom');
$result = $xml->xpath("//media:description");
foreach($result as $r){
print $r;
print '<br />';
}
The Raw xml from YouTube looks something like this.
<entry>
<id>yt:video:OTYFJaT-Glk</id>
<yt:videoId>OTYFJaT-Glk</yt:videoId>
<yt:channelId>UCtNjkMLQQOX251hjGqimx2w</yt:channelId>
<title>Guitar E.R. - Setting up wood shop for O Positive custom speaker cabinets.</title>
<link rel="alternate" href="https://www.youtube.com/watch?v=OTYFJaT-Glk"/>
<author>
<name>Guitar ER</name>
<uri>https://www.youtube.com/channel/UCtNjkMLQQOX251hjGqimx2w</uri>
</author>
<published>2020-10-18T16:38:51+00:00</published>
<updated>2020-10-20T01:04:59+00:00</updated>
<media:group>
<media:title>Guitar E.R. - Setting up wood shop for O Positive custom speaker cabinets.</media:title>
<media:content url="https://www.youtube.com/v/OTYFJaT-Glk?version=3" type="application/x-shockwave-flash" width="640" height="390"/>
<media:thumbnail url="https://i4.ytimg.com/vi/OTYFJaT-Glk/hqdefault.jpg" width="480" height="360"/>
<media:description>In this video Doctor John Moran of Guitar E.R. gives us a glimpse into the new wood shop where he will be building custom guitar and bass cabinets, likely under the name O Positive Cabinets.</media:description>
<media:community>
<media:starRating count="0" average="0.00" min="1" max="5"/>
<media:statistics views="22"/>
</media:community>
</media:group>
</entry>
<entry>
As you can see the title and uri and pretty easy to get, but I'm having trouble combining my code to get the Title, URI and Description.
Here is my code to get the Title and URI
$xml_str = file_get_contents($yt_url.$channel_id);
$xml = new SimpleXMLElement($xml_str);
foreach($xml->entry as $entry){
print $entry->title;
print '<br />';
print $entry->author->uri;
print '<br />';
}
After working on this for awhile I was able to come up with a solution, not sure if this is the best answer though.
<?
$channel_id = 'UCtNjkMLQQOX251hjGqimx2w';
$yt_url = 'https://www.youtube.com/feeds/videos.xml?channel_id=';
$xml_str = file_get_contents($yt_url.$channel_id);
$xml = new SimpleXMLElement($xml_str);
$xml->registerXPathNamespace('prefix', 'http://www.w3.org/2005/Atom');
$yt_data = array();
foreach($xml->entry as $entry){
$videoid = (string)$entry->children('yt', true)->videoId;
$yt_data[] = array(
'id' => $videoid,
'title' => (string)$entry->title,
'description' => (string)$entry->children('media', true)->group->description,
'img' => (string)'https://img.youtube.com/vi/'.$videoid.'/maxresdefault.jpg',
'thumb' => (string)'https://img.youtube.com/vi/'.$videoid.'/mqdefault.jpg',
'published' => (string)$entry->published,
'updated' => (string)$entry->updated,
'channel' => (string)$entry->children('yt', true)->channelId,
'author' => (string)$entry->author->name,
'uri' => (string)$entry->author->uri,
'views' => (string)$entry->children('media', true)->group->community->statistics->attributes()['views'],
'ratings_count' => (string)$entry->children('media', true)->group->community->starRating->attributes()['count'],
'ratings_avg' => (string)$entry->children('media', true)->group->community->starRating->attributes()['average'],
);
}
foreach($yt_data as $yt){
print '<div class="ytVidWrap">';
print '<a href="https://www.youtube.com/watch?v='.$yt['id'].'" target="_blank">';
print '<img src="'.$yt['thumb'].'" alt="YouTube Video" />';
print '<h1>'.$yt['title'].'</h1>';
print '<p>'.$yt['description'].'</p>';
print '<p>'.$yt['views'].' views • '.date('M j, Y',strtotime($yt['published'])).'</p>';
print '</a>';
print '</div>';
}
?>

RSS feed not returning anything with PHP?

I am trying to parse this feed with PHP. This is the structure of feed:
<item>
<title> ... TITLE ... </title>
<link> ... LINK .... </link>
<comments> .. COMMENTS .. </comments>
.... More tags here ....
<description><![CDATA[.. HTML ...]]></description>
</item>
This is my PHP code:
$rss = new DOMDocument();
$rss->loadHTML($feed_url);
foreach ($rss->getElementsByTagName('item') as $node) {
$description = $node->getElementsByTagName('description')->item(0)->nodeValue;
echo $description;
}
but it echoes nothing. I have tried using cURL but even then I can't echo the description tag.
What do I need to change in this code for it to work? Please let me know If I need to post the code of alternate cURL method.
loadHTML is used to load html content, to read rss use below solution
Method 1
$feed_url = 'http://thechive.com/feed/';
$rss = new DOMDocument();
$rss->load($feed_url);
foreach ($rss->getElementsByTagName('item') as $node) {
$description = $node->getElementsByTagName('description')->item(0)->nodeValue;
echo $description;
}
Method 2
$feed_url = 'http://thechive.com/feed/';
$content = file_get_contents($feed_url);
$x = new SimpleXmlElement($content);
foreach($x->channel->item as $entry) {
echo $entry->description;
}
Hope it will help you...

DOMDocument parsing right way

I have an xml from an exernal server like this:
<?xml version="1.0" encoding="UTF-8"?>
<Response ResponseReference="200002">
<ResponseDetails Language="en">
<SearchCurrencyResponse>
<CurrencyDetails>
<Currency Code="ARS"><![CDATA[Argentine Peso]]></Currency>
<Currency Code="AUD"><![CDATA[Australian Dollar]]></Currency>
</CurrencyDetails>
</SearchCurrencyResponse>
</ResponseDetails>
</Response>
What is the right way to take all currency (code and text inside)?
I have tried in this way and works but is there a way to make it more fast? Because I can have thousands of elements:
$searchCurrencyReponseElements = $xpath->query( 'ResponseDetails/SearchCurrencyResponse', $responseElement );
foreach( $searchCurrencyReponseElements as $searchCurrencyReponseElement ) {
$CurrencyElements = $xpath->query( 'CurrencyDetails/Currency', $searchCurrencyReponseElement );
foreach( $CurrencyElements as $CurrencyElement ) {
echo '<p>Currency: '.$CurrencyElement->textContent.'</p>';
}
}
And how to take the code attribute? Thanks
If you need to select all nodes by a specific node name then use DOMDocument::getElementsByTagName(). Try this:
$doc = new DOMDocument();
$doc->load($path);
// get all Currency nodes
$currencyNodes = $doc->getElementsByTagName('Currency');
// iterate over them
foreach($currencyNodes as $node) {
echo $node->getAttribute('Code') . ' ' . $node->nodeValue . PHP_EOL;
}

Php write XML file (to JW player)

I use the JW player to load a XML playlist. It works fine when I manually write the XML file, but not when I use php to parse...
I want it to look like this:
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:jwplayer="http://developer.longtailvideo.com/trac/">
<channel>
<item>
<title>Albert</title>
<media:content url="../movies/hi.mp4" />
<description></description>
<jwplayer:duration>10</jwplayer:duration>
</item>
</channel>
</rss>
The first problem is the <rss version="2.0" ...
It forces the headers to be: <?xml version="1.0"?>
The second problem is the <media:content url="" ...
How can I print out that with php ?
The third problem is how to add the end rss </rss>
My code is:
<?php
$channel = array();
$channel [] = array(
'title' => 'Albert',
'content' => 'filmer/c1.jpg',
'duration' => "10"
);
$channel [] = array(
'title' => 'Claud',
'content' => 'filmer/c2.jpg',
'duration' => "10"
);
$doc = new DOMDocument();
$doc->formatOutput = true;
$r = $doc->createElement( "channel" );
$doc->appendChild( $r );
foreach( $channel as $item )
{
$b = $doc->createElement( "item" );
$title = $doc->createElement( "title" );
$title->appendChild(
$doc->createTextNode( $item['title'] )
);
$b->appendChild( $title );
$content = $doc->createElement( "media:content" );
$content->appendChild(
$doc->createTextNode( $item['content'] )
);
$b->appendChild( $content );
$duration = $doc->createElement( "jwplayer:duration" );
$duration->appendChild(
$doc->createTextNode( $item['duration'] )
);
$b->appendChild( $duration );
$r->appendChild( $b );
}
echo $doc->saveHTML();
$doc->save("write.xml")
?>
Any ideas?
I'm a newbie in PHP/XML, sorry :/
This line: <?xml version="1.0"?> is called XML Declaration and it is optional. So whether that line is there or not should not make any difference and pose any problems as long as you use valid XML.
As RSS is based on XML, you do not need to worry about that line being there.
I hope this clarifies this part of your question.
And as Q&A normally works best with one question each, here are those other two:
remove xml version tag when a xml is created in php / PHP DomDocument output without <?xml version=“1.0” encoding=“UTF-8”?>
Generate XML with namespace URI in PHP
It's necessary to put a header before the php code in the xml to inform jwplayer what's being loaded.
header("Content-type: text/xml");

Categories