<? /***************************************************************************** * 名称:XML解析范例:XML文档信息统计 * 描述 * 本范例通过PHP的Expat解析器收集和统计XML文档的信息(例如:每个元素出现的次数、父元素和子元素 * XML文件作为一个参数 ./xmlstats_PHP4.php3 test.xml * $Requires: Expat 要求:Expat PHP4.0编译为CGI模式 *****************************************************************************/ // 第一个参数是XML文件 $file = $argv[1]; // 变量的初始化 $elements = $stack = array(); $total_elements = $total_chars = 0; // 元素的基本类 class element { var $count = 0; var $chars = 0; var $parents = array(); var $childs = array(); } // 解析XML文件的函数 function xml_parse_from_file($parser, $file) { if(!file_exists($file)) { die("Can't find file "$file"."); } if(!($fp = @fopen($file, "r"))) { die("Can't open file "$file"."); } while($data = fread($fp, 4096)) { if(!xml_parse($parser, $data, feof($fp))) { return(false); } } fclose($fp); return(true); } // 输出结果函数(方框形式) function print_box($title, $value) { printf("n+%'-60s+n", ""); printf("|%20s", "$title:"); printf("%14s", $value); printf("%26s|n", ""); printf("+%'-60s+n", ""); } // 输出结果函数(行形式) function print_line($title, $value) { printf("%20s", "$title:"); printf("%15sn", $value); } // 排序函数 function my_sort($a, $b) { return(is_object($a) && is_object($b) ? $b->count - $a->count: 0); } function start_element($parser, $name, $attrs) { global $elements, $stack; // 元素是否已在全局$elements数组中? if(!isset($elements[$name])) { // 否-增加一个元素的类实例 $element = new element; $elements[$name] = $element; } // 该元素的记数器加一 $elements[$name]->count++; // 是否有父元素? if(isset($stack[count($stack)-1])) { // 是-将父元素赋给$last_element $last_element = $stack[count($stack)-1]; // 如果目前元素的父元素数组为空,初始化为0 if(!isset($elements[$name]->parents[$last_element])) { $elements[$name]->parents[$last_element] = 0; } // 该元素的父元素记数器加一 $elements[$name]->parents[$last_element]++; // 如果目前元素的父元素的子元素数组为空,初始化为0 if(!isset($elements[$last_element]->childs[$name])) { $elements[$last_element]->childs[$name] = 0; } // 该元素的父元素的子元素记数器加一 $elements[$last_element]->childs[$name]++; } // 将目前的元素加入到栈中 array_push($stack, $name); } function stop_element($parser, $name) { global $stack; // 从栈中将最顶部的元素移去 array_pop($stack); } function char_data($parser, $data) { global $elements, $stack, $depth; // 增加目前元素的字符数目 $elements[$stack][count($stack)-1]]->chars += strlen(trim($data)); } // 产生解析器的实例 $parser = xml_parser_create(); // 设置处理函数 xml_set_element_handler($parser, "start_element", "stop_element"); xml_set_character_data_handler($parser, "char_data"); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); // 解析文件 $ret = xml_parse_from_file($parser, $file); if(!$ret) { die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser))); } // 释放解析器 xml_parser_free($parser); // 释放协助元素 unset($elements["current_element"]); unset($elements["last_element"]); // 根据元素的次数排序 uasort($elements, "my_sort"); // 在$elements中循环收集元素信息 while(list($name, $element) = each($elements)) { print_box("Element name", $name); print_line("Element count", $element->count); print_line("Character count", $element->chars); printf("n%20sn", "* Parent elements"); // 在该元素的父中循环,输出结果 while(list($key, $value) = each($element->parents)) { print_line($key, $value); } if(count($element->parents) == 0) { printf("%35sn", "[root element]"); } // 在该元素的子中循环,输出结果 printf("n%20sn", "* Child elements"); while(list($key, $value) = each($element->childs)) { print_line($key, $value); } if(count($element->childs) == 0) { printf("%35sn", "[no childs]"); } $total_elements += $element->count; $total_chars += $element->chars; } // 最终结果 print_box("Total elements", $total_elements); print_box("Total characters", $total_chars); ?>