<?php
class xmlElement
{
var $name = '';
var $attributes = array();
var $content = array();
function xmlElement($myname = '', $myattributes = array(), $mycontent = array())
{
$this->name = $myname;
$this->attributes = $myattributes;
$this->content = $mycontent;
}
}
$file = $_REQUEST['file'];
$elements = $stack = array();
$total_elements = $total_chars = 0;
$submitted = $_REQUEST; // The "$submitted" parameter normally comes from POST/GET data
// but can be used in other ways
$internalqtielementstack = array(); // Use push and pop to maintain a context list in this array
function processQtiFile($file)
{
global $internalqtielementstack;
// Initialise variables
$internalqtielementstack = array();
// Initialise the XML parser
$parser = xml_parser_create();
xml_set_element_handler($parser, 'qtiparser_start_element', 'qtiparser_stop_element');
xml_set_character_data_handler($parser, 'qtiparser_char_data');
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
//Parse the file
qtiEbVeryStart();
$ret = parseQtiXmlFromFile($parser, $file);
qtiEbVeryEnd();
if(!$ret)
die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)));
// Free the parser
xml_parser_free($parser);
}
// The function which pushes all the data through the Expat parser
function parseQtiXmlFromFile($parser, $file)
{
if(!file_exists($file))
die("Can't find file \"$file\".");
elseif(!($fp = @fopen($file, 'r')))
die("Can't find file \"$file\".");
while($data = fread($fp, 4096))
if(!xml_parse($parser, $data, feof($fp)))
return false;
fclose($fp);
return true;
}
// Expat calls this when it finds an opening tag
function qtiparser_start_element($parser, $name, $attrs)
{
global $internalqtielementstack;
$element = new xmlElement;
$element->name = $name;
$element->attributes = $attrs;
// Add it to the context list
array_push($internalqtielementstack, $element);
// Call the start function for this tag (which MUST be defined elsewhere!)
$eval='qtiebStart' . preg_replace('/\W/','',$name);
// echo "<p>$eval</p>";
if(strlen($eval)>0)
if(function_exists($eval))
$eval($attrs, $internalqtielementstack);
else
echo "\n\n<p>UNEXPECTED ELEMENT WARNING: $name</p>\n\n";
}
// Expat calls this when it finds a closing tag
function qtiparser_stop_element($parser, $name)
{
global $internalqtielementstack;
if(sizeof($internalqtielementstack)>1)
{
// Remove it from the context list
array_pop($internalqtielementstack);
}
// Call the stop function for this tag (which MUST be defined elsewhere!)
$eval='qtiebStop' . preg_replace('/\W/','',$name);
// echo "<p>$eval</p>";
if(strlen($eval)>0)
if(function_exists($eval))
$eval($internalqtielementstack);
else
echo "\n\n<p>End of unexpected element: $name</p>\n\n";
}
// Expat calls this when it finds character data
function qtiparser_char_data($parser, $data)
{
global $internalqtielementstack;
if(trim($data)!='')
{
$internalqtielementstack[sizeof($internalqtielementstack)-1]->content[] = $data;
$name = $internalqtielementstack[sizeof($internalqtielementstack)-1]->name;
// Call the data function for this tag (which MUST be defined elsewhere!)
$eval='qtiebData' . preg_replace('/\W/','',$name);
// echo "<p>$eval</p>";
if(strlen($eval)>0)
if(function_exists($eval))
$eval($internalqtielementstack, $data);
}
}
// Function used during processing, to check whether an element should be returned or not,
// according to the attributes criteria
function attributesMatchTest($criteria, $test)
{
if(sizeof($criteria)==0)
return true;
foreach($criteria as $k=>$v)
if($test[$k]!=$v)
return false;
return true;
}
?>