?
Solved

PHP and XML News Feeds

Posted on 2004-10-08
8
Medium Priority
?
417 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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 500 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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

JavaScript has plenty of pieces of code people often just copy/paste from somewhere but never quite fully understand. Self-Executing functions are just one good example that I'll try to demystify here.
Introduction This article is intended for those who are new to PHP error handling (https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html).  It addresses one of the most common problems that plague beginning PHP develop…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
HTML5 has deprecated a few of the older ways of showing media as well as offering up a new way to create games and animations. Audio, video, and canvas are just a few of the adjustments made between XHTML and HTML5. As we learned in our last micr…
Suggested Courses

741 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