Solved

PHP and XML News Feeds

Posted on 2004-10-08
8
410 Views
Last Modified: 2013-11-18
Ok, I've got an XML news feed (see example below).

== Contents of "news.xml" =========
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
      <channel>
            <title>Search Engines</title>
            <link>http://www.me.com/</link>
            <description>All About Search Engines</description>
            <copyright>(c) 2004 Me.</copyright>
      
            <item>
                  <title>Google</title>
                  <link>http://www.google.com/</link>
                  <description>All about Google</description>
                  <date>10082004</date>
            </item>
            <item>
                  <title>Yahoo!</title>
                  <link>http://www.yahoo.com/</link>
                  <description>All about Yahoo</description>
                  <date>10082004</date>
            </item>
      </channel>
</rss>
========

How can I use PHP to display it like so:
==========
<h2><a href="LINK" title="DATE">TITLE</a></h2>
<p>DESCRIPTION</p>
==========

Yes, I do know there are hundereds of examples with php & rss, but so far, i haven't been able to make any of them produce the desired results.

Thanks in advance!

0
Comment
Question by:Technokid
  • 3
  • 3
  • 2
8 Comments
 
LVL 7

Expert Comment

by:jdpipe
ID: 12265179
The easiest way is to use an clientside XSL stylesheet. Or a serverside XSL stylesheet. Or else use the RSS parsing routines from PEAR. Or else write your own parser based on the expat parser built in to php.

Is clientside XSL an option you would be happy with? I will get you more details if so.
0
 

Author Comment

by:Technokid
ID: 12265859
I'm pretty new to php, rss, & xml.
Would an XSL work just like CSS?  What is PEAR?


At the moment, I'm not concerned as much with the "style" of the words, but rather, the order and manner in which they are pulled from the xml file and displayed.
0
 
LVL 4

Expert Comment

by:duerra
ID: 12268403
Alright, so the XML cdata identifier in PHP was really messing stuff up, but regardless, this is doing what you're looking for.

This is hard for me to explain well, but it's something like this....

Every tag has 2 or 3 key/value pairs
1.  attributes
2.  value
3.  children

If the tag has no children, then that tag will not exist for it.  Children are defined as tags nested beneath that tag.

If you don't understand that following, just look at the example below.  
So, if a tag has "children", then there is an array of data beneath it, identifying those tags and their values.  Now, every tag underneath the first tag can be repeated (it's illegal to have more than one high-level tag, in this case "rss").  Because of that, there has to be a way to keep the name of the array as the key, but not overwrite the previous tag if there are multiple values for that key.  The solution?  Make the value of the key be another, numeric array, where each value is an array identifying the attributes for that tag.

<xml>
<high-level-tag>
<item</item>
<item></item>
</high-level-tag>

In this case, to get to the items, you'd navigate through the array like this:
$array['high-level-tag']['children']['item'][0];
and
$array['high-level-tag']['children']['item'][1];

Note that even if there is only one "item" tag, you still have to access it via its numerical index.  This goes for every level of nesting, beyond the first level.

Ok, that said, here's your code for your news feed, based on the XML that you posted above.

function getXMLChildren($vals, &$i)
{
      $children = array();

      while (++$i < sizeof($vals))
      {
            switch ($vals[$i]['type'])
            {
                  case 'cdata':
                        break;
                  case 'complete':
                        $children[$vals[$i]['tag']][] = array(      'attributes' => isset($vals[$i]['attributes']) ? $vals[$i]['attributes'] : false,
                                                                              'value' => $vals[$i]['value']
                              );
                        break;
                  case 'open':
                        $children[$vals[$i]['tag']][] = array(      'attributes' => isset($vals[$i]['attributes']) ? $vals[$i]['attributes'] : false,
                                                                              'value' => isset($vals[$i]['value']) ? $vals[$i]['value'] : false,
                                                                              'children' => getXMLChildren($vals, $i)
                              );
                        break;
                  case 'close':
                        return $children;
            }
      }
}

function getXMLTree($xmlData)
{
      $p = xml_parser_create();
      xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
      xml_parse_into_struct($p, $xmlData, &$vals, &$index);
      xml_parser_free($p);

      $i = 0;
      $tree = array($vals[$i]['tag'] => array('attributes' => isset($vals[$i]['attributes']) ? $vals[$i]['attributes'] : false,
                                                                  'value' => isset($vals[$i]['value']) ? $vals[$i]['value'] : false,
                                                                  'children' => getXMLChildren($vals, $i)
            ));

      return $tree;
}

$xmlData = '<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
      <channel>
            <title>Search Engines</title>
            <link>http://www.me.com/</link>
            <description>All About Search Engines</description>
            <copyright>(c) 2004 Me.</copyright>
            
            <item>
                  <title>Google</title>
                  <link>http://www.google.com/</link>
                  <description>All about Google</description>
                  <date>10082004</date>
            </item>
            <item>
                  <title>Yahoo!</title>
                  <link>http://www.yahoo.com/</link>
                  <description>All about Yahoo</description>
                  <date>10082004</date>
            </item>
      </channel>
</rss>';

$arr = GetXMLTree($xmlData);
$engines = $arr['rss']['children']['channel'][0]['children']['item'];
foreach($engines AS $engineArr)
{
      $engine = $engineArr['children'];
      echo '<h2><a href="'.$engine['link'][0]['value'].'" title="'.$engine['title'][0]['value'].'">'.$engine['title'][0]['value'].'</a></h2>';
      echo '<p>'.$engine['description'][0]['value'].'</p>';
}
0
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 

Author Comment

by:Technokid
ID: 12268419
duerra, that code looks promising.  I don't have time to test it just this second, but I should be able to get to it tomorrow.

Thanks!
0
 
LVL 4

Accepted Solution

by:
duerra earned 125 total points
ID: 12268544
I got annoyed with always having to reference tags by a numeric index beneath them, so I changed around the code.  Now, if there's more than one tag, you still have to reference it by a numeric array beneath it, but if there is only one tag, you can simply reference its values without having to access another nested array:


function getXMLChildren($vals, &$i)
{
      $children = array();

      while (++$i < sizeof($vals))
      {
            $tag = $vals[$i]['tag'];
            $type = $vals[$i]['type'];
            if($type == 'complete')
            {
                  $arr['attributes']       = isset($vals[$i]['attributes']) ? $vals[$i]['attributes'] : false;
                  $arr['value']             = $vals[$i]['value'];
            }
            elseif($type == 'open')
            {
                  $arr['attributes']       = isset($vals[$i]['attributes']) ? $vals[$i]['attributes'] : false;
                  $arr['value']             = $vals[$i]['value'];
                  $arr['children']             = getXMLChildren($vals, $i);
            }
            elseif($type == 'close')
                  { return $children; }
            else
                  { $arr = false; }
            
            if($arr)
            {
                  if(!isset($children[$tag]))
                        { $children[$tag] = $arr; }
                  else      if(isset($children[$tag][0]))
                        { $children[$tag][] = $arr; }
                  else
                  {
                        $sub = $children[$tag];
                        $children[$tag]             = array();
                        $children[$tag][]       = $sub;
                        $children[$tag][]       = $arr;
                  }
            }
      }
}

function getXMLTree($xmlData)
{
      $p = xml_parser_create();
      xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
      xml_parse_into_struct($p, $xmlData, &$vals, &$index);
      xml_parser_free($p);

      $i = 0;
      $arr = array();
      $arr['attributes']      = isset($vals[$i]['attributes']) ? $vals[$i]['attributes'] : false;
      $arr['value']            = isset($vals[$i]['value']) ? $vals[$i]['value'] : false;
      $arr['children']            = getXMLChildren($vals, $i);
      return array($vals[$i]['tag'] => $arr);
}

$xmlData = '<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
      <channel>
            <title>Search Engines</title>
            <link>http://www.me.com/</link>
            <description>All About Search Engines</description>
            <copyright>(c) 2004 Me.</copyright>
            
            <item>
                  <title>Google</title>
                  <link>http://www.google.com/</link>
                  <description>All about Google</description>
                  <date>10082004</date>
            </item>
            <item>
                  <title>Yahoo!</title>
                  <link>http://www.yahoo.com/</link>
                  <description>All about Yahoo</description>
                  <date>10082004</date>
            </item>
      </channel>
</rss>';

$arr = GetXMLTree($xmlData);
$engines = $arr['rss']['children']['channel']['children']['item'];
foreach($engines AS $engineArr)
{
      $engine = $engineArr['children'];
      echo '<h2><a href="'.$engine['link']['value'].'" title="'.$engine['title']['value'].'">'.$engine['title']['value'].'</a></h2>';
      echo '<p>'.$engine['description']['value'].'</p>';
}
0
 
LVL 7

Expert Comment

by:jdpipe
ID: 12268978
Here is the example from PEAR on how to parse an RSS feed. PEAR is a standard set of php classes that can be used to perform common tasks. It's really well worth using it because it cuts down on the amount of bespoke code you have to maintain in your projects. The url is http://pear.php.net/ for PEAR in general, and

http://pear.php.net/manual/en/package.xml.xml-rss.php

for this package. If you have experience with perl then this is like CPAN. If you know C++ then this is like STL or glibc etc.

<?php
require_once "XML/RSS.php";

$rss =& new XML_RSS("http://slashdot.org/slashdot.rdf");
$rss->parse();

echo "<h1>Headlines from <a href=\"http://slashdot.org\">Slashdot</a></h1>\n";
echo "<ul>\n";

foreach ($rss->getItems() as $item) {
    echo "<li><a href=\"" . $item['link'] . "\">" . $item['title'] . "</a></li>\n";
}

echo "</ul>\n";
?>

0
 
LVL 7

Expert Comment

by:jdpipe
ID: 12268979
You might also be interested in

http://magpierss.sourceforge.net/
0
 

Author Comment

by:Technokid
ID: 12272387
Thank you duerra!  The code is nice because it is simple and adaptive to whatever my needs are.  [ All this php stuff is new to me - I've never taken a stab at C++, java, php, or the like before, but I'm starting to like it! :D ]

Again, thank you.

A+
0

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

What is Node.js? Node.js is a server side scripting language much like PHP or ASP but is used to implement the complete package of HTTP webserver and application framework. The difference is that Node.js’s execution engine is asynchronous and event…
Password hashing is better than message digests or encryption, and you should be using it instead of message digests or encryption.  Find out why and how in this article, which supplements the original article on PHP Client Registration, Login, Logo…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

813 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now