Page 1 of 1

returned xml array troubles

Posted: Mon Jan 30, 2006 2:45 pm
by neophyte
Hey guys, I'm working through this tutorial from the Zend.com. I'm trying to make the tutorial practical for a real life scenario. Here's a sample XML:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">

<channel>
  <title>My Site</title> 
  <link>http://www.mysite.com</link> 
  <description>Visit my site</description> 
  <language>en-us</language> 
  <copyright>(C) your grandma</copyright> 
  <image>
  <title>Greetings</title>
  <link>http://www.mysite.com/</link>
  <url>http://www.mysite.com/images/logo.jpg</url>
  </image>

    
<item>
<title>Article one</title>
<link>http://www.mysite.com/article.html</link>
<pubDate>Sat, 28 Jan 2006 11:25:00 EST</pubDate>
<description><![CDATA[<p>Read this article to find out how</p>]]></description>
<category>How to</category> 
<guid isPermaLink="false">http://www.mysite.com/3172.html</guid> 
</item>
</channel>
When I run the parser code below, the first "item" title would be "My Site Article one". Thus incorrectly combining the site title and the first item's title. The second item (if the example above had one) would out put as expected -- "Article Two".

The question is how do I get the parser to make a two tiered array? Something like:

Code: Select all

array(   'site description',
                      array(  array( 'item'),
                                  array('item')
                                  array('item')
                               );
       );
I'm not sure where to get a variable to track what level I'm on or if I need a new array or whatever.

Code: Select all

<?php 
// the xml file we want to parse
$xmlSource="rssTest.xml";

$title="";
$link="";
$pubDate="";
$description="";
$category="";

$currentElement="";	//holds the name of the current element
$depth = array();
$items=array(); 	//array to hold all the movie data


function startElement($parser,$name,$attr){
		
	$GLOBALS['currentElement']=$name;	

}


function endElement($parser,$name){
	
	$elements=array('title', 'link',  'pubDate', 'description', 'category');     
	
     if(strcmp($name,"item")==0){
     
			foreach($elements as $element){
				$temp[$element]=$GLOBALS[$element];							
			}
///HERE's WHERE IT GOES INTO THE ARRAY
			 $GLOBALS['items'][]=$temp;
			
            $GLOBALS['title']="";

            $GLOBALS['link']="";

            $GLOBALS['pubDate']="";

            $GLOBALS['description']="";
            
            $GLOBALS['category']= "";
      }



}


function characterData($parser, $data) {
        $elements=array('title', 'link',  'pubDate', 'description', 'category'); 
		
        foreach ($elements as $element) {
            if ($GLOBALS["currentElement"] == $element ) {

					$GLOBALS[$element] .= $data;

            }
        }
    }


function parseFile(){
	global $xmlSource,$items;
	
	/*Creating the xml parser*/
	$xml_parser=xml_parser_create();
	
	/*Register the handlers*/
	xml_set_element_handler($xml_parser,"startElement","endElement");
	xml_set_character_data_handler($xml_parser,"characterData");
	
	/*Disables case-folding. Needed for this example*/
	xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,false);
	
	/*Open the xml file and feed it to the parser in 4k blocks*/
   if(!($fp=fopen($xmlSource,"r"))){
      die("Cannot open  $xmlSource  ");
   }
   $x =0;
   while(($data=fread($fp,4096))){
      if(!xml_parse($xml_parser,$data,feof($fp))){
	     die(sprintf("XML error at line %d column %d ", 
                      xml_get_current_line_number($xml_parser), 
                      xml_get_current_column_number($xml_parser)));
	  }
	  $x++;
   }
     
	 /*Finish ! we free the parser and returns the array*/
	 xml_parser_free($xml_parser);
	 
	 return $items;
	
}//end parseFile()



/***************************************************************************************************
		Calling the parseFile() and getting the result out in a simple html-table
***************************************************************************************************/

$result=parseFile();

print '<table border="1">';
foreach($result as $arr){

	/*check on movieId to see if we reached a new movie. 
	*	If so we print out the movieName
	*/
		if(strcmp($id,$arr["title"])!=0){
			print '
		<tr>
			<td colspan="3"><b><a href="'.$arr['link'].'">'.$arr["title"].'</a></b></td>	
		</tr>
		<tr>
			<td colspan="3">'.$arr["description"].'</td>	
		</tr>
		';
		
		}




}

print '</table>';
?>
Thanks for your help

Posted: Mon Jan 30, 2006 3:16 pm
by Burrito
wow! serendipity...I'm doing the same thing today :P

here's what I found that needs a lil' bit of tweaking but I"m on the right track with it:

http://us2.php.net/simplexml

example:

Code: Select all

$someStr = file_get_contents("test2.xml");
$xml = simplexml_load_string($someStr);
echo "<pre>";
print_r($xml);
echo "</pre>";

Posted: Mon Jan 30, 2006 4:40 pm
by neophyte
Bummer running php4! SimpleXML is for PHP5! I tried:

http://magpierss.sourceforge.net

Works brilliantly!

Using it this way for local on server rss feeds:

Code: Select all

<?php
require_once('magpierss/rss_parse.inc');
$source = file_get_contents('/home/tna/www/rssTest.xml');
		$rss = new MagpieRSS($source);								
	var_dump($rss->items);

?>
//Minor modification to rss_parse.inc needed... Path needs to be defined.

Code: Select all

if(!defined('MAGPIE_DIR'){
define('MAGPIE_DIR', '');
}

However if someone does figure out the solution to the previous problem, I would very much love to see the solution. Today has been about learning XML.

Posted: Tue Jan 31, 2006 3:51 pm
by Burrito
Neophyte does that library work with tag attributes?

simplexml only seems to put data that is in the node containers into the array.

I'd like something that will do both.

Posted: Tue Jan 31, 2006 10:37 pm
by neophyte
I lucked out, the RSS feeds I was working with don't need attribute support. But it looks like according to their site magpierss has limited attribute support. The projects to do list includes improving attribute support. Can't hurt to try...