php 处理 xml 之 解析

XML解析器的两种基本类型:

基于树型的解析器:将XML文档转换成树型结构。这类解析器分析整篇文章,同时提供一个API来访问所产生树的每个元素。其通用的标准为DOM(文档对象模式)。

基于事件的解析器:将XML文档视为一系列的事件。当一个特殊事件发生时,解析器将调用开发者提供的函数来处理。

不像基于树型的解析器,基于事件的解析器不产生描述文档的结构。在CDATA项中,基于事件的解析器不会让你得到父元素的信息。

然而,它提供一个更底层的访问,这就使得可以更好地利用资源和更快地访问。通过这种方式,就没有必要将整个文档放入内存;而事实上,整个文档甚至可以大于实际内存值。

用于产生XML解析器实例的函数为xml_parser_create()。该实例将用于以后的所有函数。这个思路非常类似于PHP中MySQL函数的连 接标记。在解析文档前,基于事件的解析器通常要求你注册回调函数-用于特定的事件发生时调用。

它定义了如下七个可能事件:

对象 XML解析函数 描述 元素 xml_set_element_handler() 元素的开始和结束

字符数据 xml_set_character_data_handler() 字符数据的开始

外部实体 xml_set_external_entity_ref_handler() 外部实体出现

未解析外部实体 xml_set_unparsed_entity_decl_handler() 未解析的外部实体出现

处理指令 xml_set_processing_instruction_handler() 处理指令的出现

记法声明 xml_set_notation_decl_handler() 记法声明的出现

默认 xml_set_default_handler() 其它没有指定处理函数的事件

所有的回调函数必须将解析器的实例作为其第一个参数(此外还有其它参数)。

元素的回调处理函数通过xml_set_element_handler()来注册。

这个函数需要三个参数:
解析器的实例
处理开始元素的回调函数的名称
处理结束元素的回调函数的名称

当开始解析XML文档时,回调函数必须存在。它们必须定义为与PHP手册中所描述的原型一致。


范例



<?  

/*****************************************************************************  

* 名称: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)))  

  

}  



fclose($fp);  



return(true);  

}  



// 输出结果函数(方框形式)

function print_box($title, $value)  

{  

printf("
+%'-60s+
", "");  

printf("|%20s", "$title:");  

printf("%14s", $value);  

printf("%26s|
", "");  

printf("+%'-60s+
", "");  

}  



// 输出结果函数(行形式)

function print_line($title, $value)  

{  

printf("%20s", "$title:");  

printf("%15s
", $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("
%20s
", "* Parent elements");  



// 在该元素的父中循环,输出结果

while(list($key, $value) = each($element->parents))  

{  

print_line($key, $value);  

}  

if(count($element->parents) == 0)  

{  

printf("%35s
", "[root element]");  

}  



// 在该元素的子中循环,输出结果

printf("
%20s
", "* Child elements");  

while(list($key, $value) = each($element->childs))  

{  

print_line($key, $value);  

}  

if(count($element->childs) == 0)  

{  

printf("%35s
", "[no childs]");  

}  



$total_elements += $element->count;  

$total_chars += $element->chars;  

}  



// 最终结果

print_box("Total elements", $total_elements);  

print_box("Total characters", $total_chars);  

?>

http://phpup.com/phparticle/show-article-688/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值