<? PHP
// Elements in xml
Class XMLTag
{
Var $ parent; // parent node
Var $ child; // subnode
Var $ attribute; // attributes of the current node
Var $ data; // Local node data
Var $ TagName; // The name of the current node.
Var $ depth; // The depth of the current node. The root node is 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;
}
// Obtain a tag node
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 Document parsing
Class XMLDoc
{
Var $ parser; // xml parsing pointer
Var $ XMLTree; // generated xml tree
Var $ XMLFile; // xml file to be parsed
Var $ XMLData; // xml data to be parsed
Var $ error; // error message
Var $ NowTag; // The node Currently pointed
Var $ TreeData; // traverses the data generated by the xml tree.
Var $ MaxDepth; // maximum depth of the current tree
Var $ encode; // encoding method of the xml document
Var $ chs; // character conversion
Function XMLDoc ()
{
// Use the default 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 file cannot be opened ';
Return false;
}
$ This-> XMLData = '';
$ This-> TreeData = '';
Return true;
}
Function SetXMLData ($ data)
{
If ($ this-> XMLFile) fclose ($ this-> XMLFile );
$ This-> XMLData = $ data;
$ This-> TreeData = '';
}
// Add a new node to the tree
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;
}
// Generate a new node
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;
}
// Start parsing the xml document
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;
}
// Determine the encoding method
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 );
}
// Modify the value of a node based on the node name
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;
}
// Modify the attributes of a node in the tree based on the node name
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-> atttiach ))
{
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;
}
// Obtain the root node
Function GetDocumentElement ()
{
Return $ this-> XMLTree;
}
// Traverse the generated xml tree and regenerate the xml document
Function compute tree ()
{
$ This-> TreeData = '';
$ This-> _ spanning tree ($ this-> XMLTree );
Return $ this-> TreeData;
}
// Recursive traversal
Function _ decision tree ($ 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-> _ response tree ($ tree-> child [$ I]);
}
$ This-> TreeData. = '</'. $ tree-> TagName. "> n ";
}
// Get error information
Function GetError ()
{
Return $ this-> error;
}
// Obtain the maximum depth of the tree
Function GetMaxDepth ()
{
Return $ this-> MaxDepth;
}
// Write the xml tree to the xml file
Function WriteToFile ($ file, $ head = '')
{
$ Fp = fopen ($ file, 'w ');
If (! $ Fp)
{
$ This-> error = 'unable to open the written file ';
Return false;
}
If (empty ($ this-> TreeData) $ this-> partial tree ();
$ Head = empty ($ head )? '<? Xml version = "1.0" standalone = "yes" encoding = "gb2312"?> ': $ Head;
Fwrite ($ fp, $ head );
Fwrite ($ fp, $ this-> TreeData );
Fclose ($ fp );
Return true;
}
}
?>