122 lines
3.2 KiB
PHP
122 lines
3.2 KiB
PHP
|
<?php
|
||
|
/* vim: set noexpandtab tabstop=2 softtabstop=2 shiftwidth=2: */
|
||
|
|
||
|
/**
|
||
|
* Builds an easy structured array out of a xml file.
|
||
|
* Element names will be the keys and the data the values.
|
||
|
*
|
||
|
* Updated by Xymph
|
||
|
*/
|
||
|
|
||
|
class Examsly {
|
||
|
var $data;
|
||
|
var $struct;
|
||
|
var $parser;
|
||
|
var $stack;
|
||
|
var $utf8enc;
|
||
|
|
||
|
/**
|
||
|
* Parses a XML structure into an array.
|
||
|
*/
|
||
|
function parseXml($source, $isfile = true, $utf8enc = false) {
|
||
|
|
||
|
// clear last results
|
||
|
$this->stack = array();
|
||
|
$this->struct = array();
|
||
|
$this->utf8enc = $utf8enc;
|
||
|
|
||
|
// create the parser
|
||
|
$this->parser = xml_parser_create();
|
||
|
xml_set_object($this->parser, $this);
|
||
|
xml_set_element_handler($this->parser, 'openTag', 'closeTag');
|
||
|
xml_set_character_data_handler($this->parser, 'tagData');
|
||
|
|
||
|
// load the xml file
|
||
|
if ($isfile)
|
||
|
$this->data = @file_get_contents($source);
|
||
|
else
|
||
|
$this->data = $source;
|
||
|
|
||
|
// escape '&' characters
|
||
|
$this->data = str_replace('&', '<![CDATA[&]]>', $this->data);
|
||
|
|
||
|
// parse xml file
|
||
|
$parsed = xml_parse($this->parser, $this->data);
|
||
|
|
||
|
// display errors
|
||
|
if (!$parsed) {
|
||
|
$code = xml_get_error_code($this->parser);
|
||
|
$err = xml_error_string($code);
|
||
|
$line = xml_get_current_line_number($this->parser);
|
||
|
trigger_error("[XML Error $code] $err on line $line", E_USER_WARNING);
|
||
|
return false;
|
||
|
}
|
||
|
return $this->struct;
|
||
|
}
|
||
|
|
||
|
private function openTag($parser, $name, $attributes) {
|
||
|
$this->stack[] = $name;
|
||
|
$this->struct[$name] = '';
|
||
|
}
|
||
|
|
||
|
private function tagData($parser, $data) {
|
||
|
if (trim($data)) {
|
||
|
$index = $this->stack[count($this->stack)-1];
|
||
|
// use raw, don't decode '+' into space
|
||
|
if ($this->utf8enc)
|
||
|
$this->struct[$index] .= rawurldecode($data);
|
||
|
else
|
||
|
$this->struct[$index] .= utf8_decode(rawurldecode($data));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private function closeTag($parser, $name) {
|
||
|
if (count($this->stack) > 1) {
|
||
|
$from = array_pop($this->stack);
|
||
|
$to = $this->stack[count($this->stack)-1];
|
||
|
$this->struct[$to][$from][] = $this->struct[$from];
|
||
|
unset($this->struct[$from]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Parses an array into an XML structure.
|
||
|
*/
|
||
|
function parseArray($array) {
|
||
|
$xmlstring = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
|
||
|
$xmlstring .= $this->parseArrayElements($array);
|
||
|
return $xmlstring;
|
||
|
}
|
||
|
|
||
|
private function parseArrayElements($array, $opt_tag = '') {
|
||
|
|
||
|
// read each element of the array
|
||
|
for ($i = 0; $i < count($array); $i++) {
|
||
|
|
||
|
// check if array is associative
|
||
|
if (is_numeric(key($array))) {
|
||
|
$xml .= '<'.$opt_tag.'>';
|
||
|
if (is_array(current($array))) {
|
||
|
$xml .= $this->parseArrayElements(current($array), key($array));
|
||
|
} else {
|
||
|
// use raw, don't encode space into '+'
|
||
|
$xml .= rawurlencode(utf8_encode(current($array)));
|
||
|
}
|
||
|
$xml .= '</'.$opt_tag.'>';
|
||
|
} else {
|
||
|
if (is_array(current($array))) {
|
||
|
$xml .= $this->parseArrayElements(current($array), key($array));
|
||
|
} else {
|
||
|
$xml .= '<'.key($array).'>';
|
||
|
// use raw, don't encode space into '+'
|
||
|
$xml .= rawurlencode(utf8_encode(current($array)));
|
||
|
$xml .= '</'.key($array).'>';
|
||
|
}
|
||
|
}
|
||
|
next($array);
|
||
|
}
|
||
|
return $xml;
|
||
|
}
|
||
|
}
|
||
|
?>
|