'__ATTRIBUTE__', 'content' => '__CONTENT__', 'count' => '__COUNT__', ); var $translate = array( '&' => '&', ''' => '\'', '"' => "\"", '<' => '<', '>' => '>', ); function xmlReader2($alwaysusekeys = NULL, $specialkeys = NULL, $translate = array()) { if ($alwaysusekeys !== NULL && is_bool($alwaysusekeys)) $this->alwaysusekeys = $alwaysusekeys; if ($specialkeys !== NULL && is_array($specialkeys)) { foreach($specialkeys as $key => $value) { if (array_key_exists($key, $this->specialkeys) && is_string($value)) $this->specialkeys[$key] = $value; } } if (is_array($translate)) { foreach($translate as $key => $value) { if (!array_key_exists($key, $this->translate) && is_string($value)) $this->translate[$key] = $value; } } } function file($filename, $iconv = array('')) { if ($fh = fopen($filename, 'r')) { $buffer = ''; while(!feof($fh)) $buffer .= fgets($fh, 4096); fclose($fh); if ($iconv['from'] && $iconv['to']) $buffer = iconv($iconv['from'], $iconv['to'], $buffer); return $this->parse($buffer); } return false; } function parse($data) { if (is_array($data)) $data = implode('', $data); return $this->_parse($data, 0); } function _parse($data, $level) { $retval = $keys = array(); $offs = 0; $cdata = strncmp('findtagend($data, $start+1); if ($end !== false) { $tmp = trim(substr($data, $start+1, $end-$start-1)); if ($tmp[0] == '?' || $tmp[0] == '!') { if ($level) { $offs = $end+1; continue; } $tmp = trim(substr($data, $start+2, $end-$start-(2+($tmp[0] == '?')))) . '/'; } $t = $this->explode(' ',trim($tmp, '/')); for($i = 0; $i < count($t); $i++) $t[$i] = trim($t[$i]); $key = $t[0]; $prop = array(); if ($t[1]) { for($i = 1;$i < count($t); $i++) { $eq = strpos($t[$i], '='); if ($eq) $prop[substr($t[$i], 0, $eq)] = $this->decode(trim(substr($t[$i], $eq+1), "'\"")); else $prop[] = trim($t[$i], "'\""); } } $d = array(); if ($tmp[strlen($tmp)-1] == '/') { if (!empty($prop)) $d[$this->specialkeys['attribute']] = $prop; $offs = $end+1; } else { // TODO: skip tags in CDATA $start = $end+1; $bpos = $epos = $end; $opened = 1; do { while($opened && $epos !== false) { $epos = strpos($data, "", $epos+1); if ($epos !== false) $opened--; } if ($epos !== false) { do { $bp1 = strpos($data, "<$key>", $bpos+1); do { $closed = false; $bp2 = strpos($data, "<$key ", $bpos+1); if ($bp2 !== false) { $e = $this->findtagend($data, $bp2+1); if ($e !== false && $data[$e-1] == '/') { $bpos = $e; $closed = true; } } } while($closed); $bp = $bp1; if ($bp2 !== false) { if ($bp === false) $bp = $bp2; elseif ($bp > $bp2) $bp = $bp2; } if ($bp !== false && $bp < $epos) { $bpos = $bp; $opened++; } } while($bp !== false && $bp < $epos); } } while($opened && $epos !== false); $end = $epos; if ($end !== false) { if ($end > $start) { $d = $this->_parse(substr($data, $start, $end-$start), $level+1); if (count($prop)) $d[$this->specialkeys['attribute']] = $prop; } $offs = $end+strlen(""); } else $offs = $start+1; } switch(count($d)) { case 0: $d = $this->alwaysusekeys ? array($this->specialkeys['content'] => '') : ''; break; case 1: if (!$this->alwaysusekeys) { if (array_key_exists($this->specialkeys['content'], $d)) $d = $d[$this->specialkeys['content']]; elseif (array_key_exists($this->specialkeys['attribute'], $d)) $d = $d[$this->specialkeys['attribute']]; } } if (isset($retval[$key])) { if ($keys[$key] == 1) $retval[$key] = array($this->specialkeys['count'] => 1, $retval[$key]); $retval[$key][] = $d; $retval[$key][$this->specialkeys['count']]++; } else $retval[$key] = $d; $keys[$key]++; } else $offs = strlen($data); } else { $d = substr($data, $offs); if (strlen(trim($d))) $retval[$this->specialkeys['content']] = $d; break; } } } else { $data = $cdata ? substr(trim($data), 9, -3) : $this->decode($data); if ($cdata && $this->alwaysusekeys) $retval[$this->specialkeys['content']]['CDATA'] = $data; else $retval[$this->specialkeys['content']] = $data; } return $retval; } function findtagend($data, $offs) { // TODO: skip in CDATA and property value $bpos = $epos = $offs; $opened = 1; do { while($opened && $epos !== false) { $epos=strpos($data, '>', $epos+1); if ($epos !== false) $opened--; } if ($epos !== false) { do { $bp = strpos($data, '<', $bpos+1); if ($bp !== false && $bp < $epos) { $bpos = $bp; $opened++; } } while($bp !== false && $bp < $epos); } } while($opened && $epos !== false); return $epos; } function explode($sep, $str) { $seplen = strlen($sep); $i = 0; while ($i < strlen($str)) { for($i = 0; ($i < strlen($str)) && (substr($str, $i, $seplen) != $sep); $i++) { if ($str[$i] == '\'') $i = strpos($str, '\'', $i+1); if ($str[$i] == "\"") $i = strpos($str, "\"", $i+1); if ($i === false) $i = strlen($str); } if (substr($str, $i, $seplen) == $sep) { $result[] = substr($str, 0, $i); $str = substr($str, $i+$seplen); $i = 0; } } $result[] = $str; return $result; } function decode($str) { return strtr($str, $this->translate); } } class xmlWriter2 { var $lengthusecdata = 64; var $specialkeys = array( 'attribute' => '__ATTRIBUTE__', 'content' => '__CONTENT__', 'count' => '__COUNT__', ); var $translate = array( '&' => "&", '\'' => "'", "\"" => """, '<' => "<", '>' => ">", ); function xmlWriter2($lengthusecdata = NULL, $specialkeys = NULL, $translate = array()) { if ($lengthusecdata !== NULL && is_int($lengthusecdata)) $this->lengthusecdata = $lengthusecdata; if ($specialkeys !== NULL && is_array($specialkeys)) { foreach($specialkeys as $key => $value) { if (array_key_exists($key, $this->specialkeys) && is_string($value)) $this->specialkeys[$key] = $value; } } if (is_array($translate)) { foreach($translate as $key => $value) { if (!array_key_exists($key, $this->translate) && is_string($value)) $this->translate[$key] = $value; } } } function file($filename, $data, $encoding, $version = '1.0', $iconv = array('')) { if ($fh = fopen($filename, 'w')) { $buffer = create($data, $encoding, $version); if ($iconv['from'] && $iconv['to']) $buffer = iconv($iconv['from'], $iconv['to'], $buffer); $cnt = fputs($fh, $buffer); fclose($fh); return $cnt; } return false; } function create($data, $encoding, $version = '1.0') { $str = "\n"; $str .= $this->element($data); return $str; } function element($data) { return $this->_element($data, 0); } function _element($data, $level = 0) { if (is_array($data)) { $p = ''; for($i = 0; $i < $level; $i++) $p .= "\t"; $str = ''; foreach($data as $key => $values) { if (!$this->validtag($key)) { trigger_error('XML writer: "' . $key . '" tag name is invalid, skipping!', E_USER_WARNING); continue; } if (is_array($values)) { $keys = array_keys($values); $numkeys = count(array_filter($keys, 'is_numeric')); $keys = count($keys)-(int)array_key_exists($this->specialkeys['attribute'], $values); } else { $keys = 0; $numkeys = 0; } if (!$numkeys || $numkeys != $keys) { $dcnt = 0; $tag = "$p<$key"; if (is_array($values[$this->specialkeys['attribute']])) { foreach($values[$this->specialkeys['attribute']] as $k => $v) { if (!$this->validtag($k)) { trigger_error('XML writer: "' . $k . '" attribute name is invalid, skipping!', E_USER_WARNING); continue; } $tag .= " $k=\"" . $this->encode($v) . "\""; $dcnt++; } unset($values[$this->specialkeys['attribute']]); } $value = is_array($values) && array_key_exists($this->specialkeys['content'], $values) ? $values[$this->specialkeys['content']] : $values; $array = is_array($value); if ((!$array && strlen($value)) || ($array && count($value))) { $dcnt++; $tag .= '>'; if ($array) $tag .= "\n" . $this->_element($value,$level+1) . "$p"; else { if ($this->lengthusecdata > -1 && strlen($value) > $this->lengthusecdata && strpos($value, '') === false) $tag .= ""; else $tag .= $this->encode($value); } $tag .= "\n"; } else $tag .= "/>\n"; if ($dcnt) $str .= $tag; } elseif (is_array($values)) { foreach($values as $value) { $str .= $this->_element(array($key => $value), $level); } } else $str .= $this->_element($values); } return $str; } else return $this->encode($data); } function validtag($tag) { return preg_match('/^[a-z_][a-z0-9_]*$/mi',$tag); } function encode($str) { return strtr($str, $this->translate); } } ?>