Solved

PHP and XML News Feeds

Posted on 2004-10-08
8
397 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 

Author Comment

by:Technokid
Comment Utility
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
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 4

Accepted Solution

by:
duerra earned 125 total points
Comment Utility
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
Comment Utility
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
Comment Utility
You might also be interested in

http://magpierss.sourceforge.net/
0
 

Author Comment

by:Technokid
Comment Utility
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 your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

SASS allows you to treat your CSS code in a more OOP way. Let's have a look on how you can structure your code in order for it to be easily maintained and reused.
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

762 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

10 Experts available now in Live!

Get 1:1 Help Now