Solved

PHP and XML News Feeds

Posted on 2004-10-08
8
408 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
 

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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Load google maps api into wordpress 5 37
mysqli 3 22
Whether to store ID's or text values for detailed information 3 22
Problem sending file attachments 8 24
This article covers the basics of the Sass, which is a CSS extension language. You will learn about variables, mixins, and nesting.
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

861 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

28 Experts available now in Live!

Get 1:1 Help Now