<?php

/*******************************************************************************
 * Copyright (c) 2006 Eclipse Foundation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Wayne Beaton (Eclipse Foundation)- initial API and implementation
 *******************************************************************************/

#*****************************************************************************
#
# ** THIS FUNCTIONALITY IN THIS FILE IS DEPRECATED.
# ** USE THE XML_SIMPLE APIS INSTEAD.
#
# news.php
#
# Author: 		Wayne Beaton
# Date:			2005-11-07
#
# Description: This file contains code to assist with using a SAX parser
# on an XML file. Beware: it's weird.
#
#****************************************************************************

/*
 * This function does the actual work of parsing the RSS
 * file into an object representation. We use a SAX parser
 * to do this.
 * 
 * Note that this function is intended to be used with relatively
 * short files (the entire file contents are loaded into memory).
 * If the RSS files start to get too large, this method will need
 * to be updated.
 * @deprecated
 */
function parse_xml_file($file_name, & $file_handler) {
	$file_handler->initialize();
	
	// Read the entire file contents in to memory.
	// If file sizes get too large, we'll have to be smarter here.
	$file = fopen($file_name, "r");
	$xml = fread($file, filesize($file_name));
	fclose($file);
	
	parse_xml_string($xml, $file_handler);
}

function parse_xml_string($xml, & $file_handler) {
	$GLOBALS['handler'] = $file_handler;
	$parser = xml_parser_create();
	xml_set_element_handler($parser, 'sax_start_handler', 'sax_end_handler');
	xml_set_character_data_handler($parser, 'sax_data_handler');
	xml_parse($parser, $xml);
	if (xml_get_error_code($parser)) throw new SaxParsingException(xml_error_string($parser));
}

class SaxParsingException extends Exception {
	public function __construct($message, $code = 0) {
		parent::__construct($message, $code);
	}
}


/*
 * The $handler variable is global. It manages all the call backs
 * that come (indirectly) from the SAX parser.
 */
$handler = null;

/*
 * SAX parser callback method to handle the start of an element.
 * This method just defers to the global handler to do the actual
 * work.
 */
function sax_start_handler($parser, $name, $attributes) {
	global $handler;
	$handler->start($name, $attributes);
}

/*
 * SAX parser callback method to handle the text for an element.
 * This method just defers to the global handler to do the actual
 * work.
 */
function sax_data_handler($parser, $data) {
	global $handler;
	$handler->data($data);
}

/*
 * SAX parser callback method to handle the end of an element.
 * This method just defers to the global handler to do the actual
 * work.
 */
function sax_end_handler($parser, $name) {
	global $handler;
	$handler->end($name);
}

/*
 * The XmlHandler class is the focal point of the SAX parser callbacks.
 * It keeps track of a stack of element handlers. The element handlers
 * are used to handle whatever elements come in.
 */
class XmlFileHandler {
	var $stack;

	function XmlFileHandler() {
		$this->stack = array ();
	}
	
	function initialize() {
		$element_handler = $this->get_root_element_handler();
		array_push($this->stack, $element_handler);
	}
	
	function get_root_element_handler() {
		return new DoNothingHandler();
	}
	
	function end_root_element_handler($handler) {
	}

	/*
	 * Handle the start callback. Here, we get the current element handler
	 * from the top of the stack and ask it what to do. The element handler
	 * is asked to provide a new handler to handle the new element. That new
	 * handler is put on the top of the stack and will handle all future
	 * callbacks until it is removed (by the end method).
	 */
	function start($name, $attributes) {
		$handler = & array_last($this->stack);
		$next = & $handler->get_next($name, $attributes);
		array_push($this->stack, $next);
	}

	/*
	 * Data has been encountered, send the data to the current element handler
	 * to sort out what needs to be done.
	 */
	function data($data) {
		$handler = & array_last($this->stack);
		$handler->data($data);
	}

	/*
	 * The end of an element has occurred. Pop the current element handler
	 * from the top of the stack and tell it that it's work is done.
	 */
	function end($name) {
		$handler = & array_pop($this->stack);
		$handler->end($name);
		
		$next_handler = & array_last($this->stack);
		$next_handler->end_handler($name, $handler);
		
		// If we've just popped off the last actual element handler, leaving
		// only the root handler at the top of the stack, send it the end message.
		if (count($this->stack) == 1) 
			$this->end_root_element_handler($handler);
	}
}

class XmlElementHandler {
	function & get_next($name, $attributes) {
		$method_name = "get_" . str_replace("-", "_", $name) . "_handler";
		if (method_exists($this, $method_name)) {
			return $this->$method_name($attributes);
		} else {
			return new DoNothingHandler();
		}
	}

	function end_handler($name, $handler) {
		$method_name = "end_" . str_replace("-", "_", $name) . "_handler";
		if (method_exists($this, $method_name)) {
			return $this->$method_name($handler);
		} 
	}
	
	function initialize() {
	}
	
	/*
	 * Ignore data for this element.
	 */
	function data($data) {
	}

	function start($name) {
	}
	
	/*
	 * Ignore data for this element.
	 */
	function end($name) {
	}
}

class SimpleTextHandler extends XmlElementHandler {
	var $text;

	function & get_next($name, $attributes) {
		return new DoNothingHandler();
	}

	function data($data) {
		$this->text .= $data;
	}
	
	function end($name) {
		$this->text = html_entity_decode($this->text);
	}
}

class SimplePropertyHandler extends SimpleTextHandler {
	var $owner;
	var $property;

	function SimplePropertyHandler(& $owner, $property) {
		$this->owner = & $owner;
		$this->property = $property;
	}

	function end($name) {
		parent::end($name);
		$this->set_property_value($this->text);
	}

	function set_property_value(& $value) {
		$property = $this->property;
		$this->owner-> $property = $value;
	}
}

class DoNothingHandler extends XmlElementHandler {
	function & get_next($name, $attributes) {
		return $this;
	}
}

function & array_last(& $array) {
	return $array[count($array) - 1];
}

?>