<?PHP
//xml中的元素
class XMLTag
{
var $parent;//父節點
var $child;//子節點
var $attribute;//本節點屬性
var $data;//本節點資料
var $TagName;//本節點名稱
var $depth;//本節點的深度,根節點為1
function XMLTag($tag='')
{
$this->attribute = array();
$this->child = array();
$this->depth = 0;
$this->parent = null;
$this->data = '';
$this->TagName = $tag;
}
function SetTagName($tag)
{
$this->TagName = $tag;
}
function SetParent(&$parent)
{
$this->parent = &$parent;
}
function SetAttribute($name,$value)
{
$this->attribute[$name] = $value;
}
function AppendChild(&$child)
{
$i = count($this->child);
$this->child[$i] = &$child;
}
function SetData($data)
{
$this->data= $data;
}
function GetAttr()
{
return $this->attribute;
}
function GetProperty($name)
{
return $this->attribute[$name];
}
function GetData()
{
return $this->data;
}
function GetParent()
{
return $this->parent;
}
function GetChild()
{
return $this->child;
}
function GetChildByName($name)
{
$total = count($this->child);
for($i=0;$i<$total;$i++)
{
if($this->child[$i]->attribute['name'] == $name)
{
return $this->child[$i];
}
}
return null;
}
//擷取某個tag節點
function GetElementsByTagName($tag)
{
$vector = array();
$tree = &$this;
$this->_GetElementByTagName($tree,$tag,$vector);
return $vector;
}
function _GetElementByTagName($tree,$tag,&$vector)
{
if($tree->TagName == $tag) array_push($vector,$tree);
$total = count($tree->child);
for($i = 0; $i < $total;$i++)
$this->_GetElementByTagName($tree->child[$i],$tag,$vector);
}
}
//xml文檔解析
class XMLDoc
{
var $parser;//xml解析指標
var $XMLTree;//產生的xml樹
var $XMLFile;//將要解析的xml文檔
var $XMLData;//將要解析的xml資料
var $error;//錯誤資訊
var $NowTag;//當前指向的節點
var $TreeData;//遍曆產生的xml樹等到的資料
var $MaxDepth;//本樹最大的深度
var $encode;//xml文檔的編碼方式
var $chs;//字元轉換
function XMLDoc()
{
//採用預設的ISO-8859-1
$this->parser = xml_parser_create();
xml_parser_set_option($this->parser,XML_OPTION_CASE_FOLDING,0);
xml_set_object($this->parser,&$this);
xml_set_element_handler($this->parser,'_StartElement','_EndElement');
xml_set_character_data_handler($this->parser,'_CData');
$this->stack = array();
$this->XMLTree = null;
$this->NowTag = null;
$this->MaxDepth = 0;
}
function LoadFromFile($file)
{
$this->XMLFile = fopen($file,'r');
if(!$this->XMLFile)
{
$this->error = '不能開啟xml檔案';
return false;
}
$this->XMLData = '';
$this->TreeData = '';
return true;
}
function SetXMLData($data)
{
if($this->XMLFile) fclose($this->XMLFile);
$this->XMLData = $data;
$this->TreeData = '';
}
//給樹添加一個新的節點
function AppendChild(&$child)
{
if($this->XMLTree == null)
{
$child->depth = 1;
$this->XMLTree = &$child;
$this->NowTag = &$this->XMLTree;
}
else
{
$i = count($this->NowTag->child);
$this->NowTag->child[$i] = &$child;
$child->parent = &$this->NowTag;
$child->depth = $this->NowTag->depth+1;
unset($this->NowTag);
$this->NowTag = &$child;
}
$this->MaxDepth = ($this->MaxDepth < $this->NowTag->depth)?$this->NowTag->depth:$this->MaxDepth;
}
//產生一個新的節點
function &CreateElement($tag)
{
$element = new XMLTag($tag);
return $element;
}
function _StartElement($parser,$element,$attribute)
{
$tag = new XMLTag();
$tag->TagName = $element;
$tag->attribute = $attribute;
if($this->XMLTree == null)
{
$tag->parent = null;
$tag->depth = 1;
$this->XMLTree = &$tag;
$this->NowTag = &$tag;
}
else
{
$i = count($this->NowTag->child);
$this->NowTag->child[$i] = &$tag;
$tag->parent = &$this->NowTag;
$tag->depth = $this->NowTag->depth+1;
unset($this->NowTag);
$this->NowTag = &$tag;
}
$this->MaxDepth = ($this->MaxDepth < $this->NowTag->depth)?$this->NowTag->depth:$this->MaxDepth;
}
function _CData($paraser,$data)
{
$this->NowTag->data = $data;
}
function _EndElement($parser,$element)
{
$parent = &$this->NowTag->parent;
unset($this->NowTag);
$this->NowTag = &$parent;
}
//開始解析xml文檔
function parse()
{
if($this->XMLFile)
{
$this->XMLData = '';
while(!feof($this->XMLFile))
{
$this->XMLData .= fread($this->XMLFile,4096);
}
}
fclose($this->XMLFile);
if($this->XMLData)
{
//$this->JudgeEncode();
if (!xml_parse($this->parser, $this->XMLData))
{
$code = xml_get_error_code($this->parser);
$col = xml_get_current_column_number($this->parser);
$line = xml_get_current_line_number($this->parser);
$this->error = "XML error: $col at line $line:".xml_error_string($code);
return false;
}
}
xml_parser_free($this->parser);
return true;
}
//確定編碼方式
function JudgeEncode()
{
$start = strpos($this->XMLData,'<?xml');
$end = strpos($this->XMLData,'>');
$str = substr($this->XMLData,$start,$end-$start);
$pos = strpos($str,'encoding');
if($pos !== false)
{
$str = substr($str,$pos);
$pos = strpos($str,'=');
$str = substr($str,$pos+1);
$pos = 0;
while(empty($str[$pos])) $pos++;
$this->encode = '';
while(!empty($str[$pos]) && $str[$pos] != '?')
{
if($str[$pos] != '"' && $str[$pos] != "'")
$this->encode .= $str[$pos];
$pos++;
}
}
$this->chs = new Chinese('UTF-8',$this->encode);
}
//根據節點名稱修改某個節點的值
function ChangeValueByName($name,$name,$value)
{
return $this->_ChangeValueByName($this->XMLTree,$name,$value);
}
function _ChangeValueByName($tree,$name,$value)
{
if(is_array($tree->attribute))
{
while (list($k,$v) = each($tree->attribute))
{
if($k = 'name' && $v = $name)
{
$tree->data = $value;
return true;
}
}
}
$total = count($tree->child);
for($i = 0;$i<$total;$i++)
{
$result = $this->_ChangeValueByName($tree->child[$i],$name,$value);
if($result == true) break;
}
return $result;
}
//根據節點名稱修改樹中某個節點的屬性
function ChangeAttrByName($name,$attr,$value)
{
return $this->_ChangeAttrByName($this->XMLTree,$name,$attr,$value);
}
function _ChangeAttrByName(&$tree,$name,$attr,$value)
{
if(is_array($tree->attribute))
{
while(list($k,$v) = each($tree->atttibute))
{
if($k == 'name' && $v == $name)
{
$tree->attribute[$attr] = $value;
return true;
}
}
}
$total = count($tree->child);
for($i = 0;$i<$total;$i++)
{
$result = $this->_ChangeAttrByName($tree->child[$i],$name,$attr,$value);
if($result == true) break;
}
return $result;
}
//擷取根節點
function GetDocumentElement()
{
return $this->XMLTree;
}
//遍曆產生的xml樹,重建xml文檔
function WalkTree()
{
$this->TreeData = '';
$this->_WalkTree($this->XMLTree);
return $this->TreeData;
}
//遞迴遍曆
function _WalkTree($tree)
{
$this->TreeData .= '<'.$tree->TagName.' ';
if(is_array($tree->attribute))
{
while(list($key,$value) = each($tree->attribute))
{
$this->TreeData .="$key=/"$value/" ";
}
}
$this->TreeData .= '>'.$tree->data;
$total = count($tree->child);
for($i=0;$i<$total;$i++)
{
$this->_WalkTree($tree->child[$i]);
}
$this->TreeData .= '</'.$tree->TagName.">/n";
}
//擷取錯誤資訊
function GetError()
{
return $this->error;
}
//擷取樹的最大深度
function GetMaxDepth()
{
return $this->MaxDepth;
}
//將xml樹寫入xml檔案
function WriteToFile($file,$head='')
{
$fp = fopen($file,'w');
if(!$fp)
{
$this->error = '無法開啟寫入檔案';
return false;
}
if(empty($this->TreeData)) $this->WalkTree();
$head = empty($head)?'<?xml version="1.0" standalone="yes" encoding="gb2312"?>':$head;
fwrite($fp,$head);
fwrite($fp,$this->TreeData);
fclose($fp);
return true;
}
}
?>