Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 427
  • Last Modified:

PHP and XML News Feeds

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
Technokid
Asked:
Technokid
  • 3
  • 3
  • 2
1 Solution
 
jdpipeCommented:
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
 
TechnokidAuthor Commented:
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
 
duerraCommented:
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!

 
TechnokidAuthor Commented:
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
 
duerraCommented:
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
 
jdpipeCommented:
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
 
jdpipeCommented:
You might also be interested in

http://magpierss.sourceforge.net/
0
 
TechnokidAuthor Commented:
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

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

  • 3
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now