数
据。
对于
文档中每个元素,以下信息都将被输出:
该元素在文档中使用的次数
该元素中字符数据的数量
元素的父元素
元素的子元素
注意:为了
演示,我们利用PHP来产生一个结构来保存元素的父元素和子元素
准备
用于产生XML解析器实例的函数为xml_parser_create()。该实例将用于以后的所有函数。这个思路非
常类似于PHP中MySQL函数的连接标记。在解析文档前,基于事件的解析器通常要求你注册回调函数-
用于特定的事件发生时调用。Expat没有例外事件,它定义了如下七个可能事件:
对象 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手册中所描述的原型一致。
例如,Expat将三个参数传递给开始元素的处理函数。在脚本范例中,其定义如下:
function start_element($parser, $name, $attrs)
第一个参数是解析器标示,第二个参数是开始元素的名称,第三参数为包含元素所有属性和值的数
组。
一旦你开始解析XML文档,Expat在遇到开始元素是都将调用你的start_element()函数并将参数传递过
去。
XML的Case Folding选项
用xml_parser_set_option()函数将Case folding选项关闭。这个选项默认是打开的,使得传递给处理
函数的元素名自动转换为大写。但XML对大小写是敏感的(所以大小写对统计XML文档是非常重要
的)。对于我们的范例,case folding选项必须关闭。
解析文档
在完成所有的准备工作后,现在脚本终于可以解析XML文档:
Xml_parse_from_file(),一个自定义的函数,打开参数中指定的文件,并以4kb的大小进行解析
xml_parse()和xml_parse_from_file()一样,当发生错误时,即XML文档的格式不完全时,将会返回
false。
你可以使用xml_get_error_code()函数来得到最后一个错误的数字代码。将此数字代码传递给
xml_error_string()函数即可得到错误的文本信息。
输出XML当前的行数,使得调试更容易。
在解析的过程中,调用回调函数。
描述文档结构
当解析文档时,对于Expat需要强调
问题的是:如何保持文档结构的基本描述?
如前所述,基于事件的解析器本身并不产生任何结构信息。
不过标签(tag)结构是XML的重要特性。例如,元素序列
,栈的填充如下:
开始元素book:将"book"赋给栈的第一个元素($stack[0])。
开始元素title:将"title"赋给栈的顶部($stack[1])。
结束元素title:从栈中将最顶部的元素移去($stack[1])。
结束元素title:从栈中将最顶部的元素移去($stack[0])。
PHP3.0通过一个$depth变量手动控制
元素的嵌套来实现范例。这就使脚本看起来比较复杂。PHP4.0通
过array_pop()和array_push()两个函数来使脚本看起来更简洁。
收集数据
为了收集每个元素的信息,脚本需要记住每个元素的事件。通过使用一个全局的数组变量$elements来
保存文档中所有不同的元素。数组的项目是元