17.3在PHP中处理XML
17.3 在PHP中处理XML
虽然PHP在以前的版本中就已经提供了对XML的支持,但是随着PHP5的出现,这种支持大大增强了。由于PHP4对XML的支持比较有限,比如默认情况下只提供基于SAX的解析器、PHP4DOM没有实现W3C标准等。
PHP5包括彻底重新编写的和新增加的扩展,如SAX解析器、DOM、SimpleXML、XMLReader、XMLWriter和XSLT处理程序。所有这些扩展都以libxml2为基础。除了自PHP4改进的SAX支持以外,PHP5还同时支持符合W3C标准的DOM和SimpleXML扩展。默认情况下同时支持SAX、DOM和SimpleXML。如果熟悉其他语言中的DOM,使用PHP实现类似的功能会更简单。
17.3.1 在PHP中建立对XML的支持
通常,在Windows安装PHP5时,对XML的支持就已经建立,读者可以通过使用向页面输出函数phpinfo()的内容查看当前的PHP是否对XML支持,如图17-4、图17-5及图17-6所示。

图17-4 PHP中对XML的DOM支持

图17-5 PHP中的SimpleXML信息

图17-6 PHP中对XML支持的其他相关信息
17.3.2 用PHP函数处理XML文档
Expat是PHP脚本语言的XML解析器,亦称为XML处理器,是一种基于事件的解析器,它提供了一系列函数可以使程序访问XML文档的结构和内容。XML解析器有如下两种基本类型。
·基于树形的解析器:将XML文档转换成树型结构。这类解析器分析整篇文章,同时提供一个API来访问所产生树的每个元素。其通用的标准为DOM,即文档对象模式。
·基于事件的解析器,将XML文档视为一系列的事件。当一个特殊事件发生时,解析器将调用开发者提供的函数来处理。基于事件的解析器有一个XML文档的数据集中视图,也就是说它集中在XML文档的数据部分,而不是其结构。这些解析器从头到尾处理文档,并将类似于元素的开始、元素的结尾、特征数据的开始等事件通过回调(callback)函数报告给应用程序。
这里简单解释一下基于事件的XML解析器,请看下面的XML代码片段。
<title>Learning PHP5</title>
对于基于事件的XML分析器,会将面的XML代码片段分析为如下事件。
·元素开始:title。
·CDATA部分开始,value:Learning PHP5。
·元素结束:title。
本节先为读者介绍这些XML处理函数,即Expat所提供的函数,最后再通过一个具体实例讲解这些函数的具体用法。
从Apache1.3.22开始,Expat已经作为Apache的一部分。在UNIX系统中,可以通过-with-xml选项配置PHP将其编译入PHP。如果将PHP编译为Apache的模块,Expat将默认作为Apache的一部分。在Windows中,则必须要加载XML动态链接库。
17.3.3 XML解析器的建立和释放
函数xml_parser_create()用来初始化一个XML解析器,即建立XML解析器的实例,该实例将用于以后的所有函数。这一点非常类似于PHP中MySQL函数的连接。该函数语法如下。
resource xml_parser_create([string $encoding])
该函数建立一个新的XML解析器,并返回可被其他XML函数使用的资源句柄。该函数有一个可选参数,用来指定要被解析的XML输入的字符编码方式。PHP5开始,可以自动侦测输入的XML编码,因此$encoding参数仅用来指定解析后输出数据的编码。默认输出的字符编码是ISO-8859-1,而PHP5.0.2及以上版本是UTF-8。
函数xml_parser_free()用来释放指定的XML解析器,语法如下。
bool xml_parser_free (resource $parser)
参数$parser是要释放的XML解析器的指针。如果参数$parser没有指向一个合法的解析器,该函数将返回FALSE,否则将释放指定的解析器并返回TRUE。
17.3.4 处理XML元素的函数
函数xml_set_element_handler()用来处理建立起始和终止元素处理器,用法如下。
bool xml_set_element_handler (resource $parser, callback $start_elem_handler, callback $end_elem_handler )
函数xml_set_element_handler()的第1个参数$parser是指向要调用处理器的XML解析器的指针参数,第2个参数$start_elem_handler和第3个参数$end_elem_handler是表示函数名称的字符串。如果处理器被成功建立,该函数将返回TRUE。如果参数$parser指向的不是合法的解析器,该函数将返回FALSE。
第2个参数$start_elem_handler所指定的函数将在一个元素开始的时候调用,也就是说,当XML分析器遇到元素开始事件时,就会调用参数$start_elem_handler所指定的函数。同理,遇到元素结束事件时,该函数就会调用参数$end_elem_handler所指定的函数。
由参数$start_elem_handler所指定的函数,必须有3个参数,各参数解释如下所述。
·第1个参数parser,是指向要调用XML解析器的指针。
·第2个参数name,为该处理器所调用的元素名。
·第3个参数data,是一个包含有对应元素的属性的数组,数组元素的下标为属性名,元素的值即为属性的值。
类似地,由参数$end_elem_handler所指定的函数必须包含两个参数,各参数解释如下所述。
·第1个参数parser,是指向要调用XML解析器的指针。
·第2个参数name,为该处理器所调用的元素名。
本章第17.5.5小节的实例代码有该函数的具体应用,读者可以仔细研究有关代码,以便准确理解本小节所述内容。
17.3.5 处理XML字符数据的函数
函数xml_set_character_data_handler()用来建立字符数据处理器,用法如下。
bool xml_set_character_data_handler (resource $parser, callback $handler)
该函数是参数$parser指向的XML解析器指定字符数据处理函数。参数$handler是一个表示函数名称的字符串。由参数$handler所指定的函数,将在分析器遇到一个字符数据事件时调用。如果处理器被成功的建立,该函数将返回TRUE。如果参数$parser指向的不是合法的解析器,该函数将返回FALSE。
该函数和函数xml_set_element_handler()极为类似,由参数$handler所指定的函数必须含有两个参数,各参数解释如下所述。
·第1个参数parser,是指向要调用XML解析器的指针。
·第2个参数data,是包含有字符数据的字符串。
17.3.6 解析一个XML文档
函数xml_parse()用来解析一个XML文档,语法如下。
int xml_parse (resource $parser, string $data [, bool $is_final])
函数xml_parse()的第1个参数$parser是一个指向XML解析器的指针,第2个参数是需要解析的数据集。可以多次对新的数据调用xml_parse()函数来分段解析一个文档,这时,只要在解析最后一段数据时将参数$is_final的值设置为TRUE即可。第3个参数,如果被设置为TRUE,则data为当前解析中最后一段数据。
17.3.7 完整实例分析
这小节将通过一个具体实例使读者了解这些函数在PHP程序中的具体用法。使用的XML文档就是在17.2小节创建的17-1.xml。
这节的实例程序将首先在PHP程序中初始化XML分析器,然后为不同的XML事件定义不同的处理器,最后分析XML文档。代码17-2是实例的完整程序,执行结果如图17-7所示。
代码17-2 使用Expat函数处理XML文档17-2.php
01 <?php
02 $parser=xml_parser_create(); //
初始化XML
分析器
03
04 function start($parser,$elem_name,$elem_attrs) //
在一个元素开始时调用的函数
05 {
06 switch($elem_name)
07 {
08 case "BOOKS":
09 echo "<b>--
图书信息 --</b><br/><br/>";
10 break;
11 case "TITLE":
12 echo "<b>
书名: </b>";
13 break;
14 case "AUTHOR":
15 echo "<b>
作者: </b>";
16 break;
17 case "PUBLISHER":
18 echo "<b>
出版社: </b>";
19 break;
20 case "PRICE":
21 echo "<b>
价格: </b>";
22 break;
23 }
24 }
25
26 function stop($parser,$elem_name) //
在一个元素结束时调用的函数
27 {
28 echo "<br />";
29 }
30
31 function char($parser,$data) //
当找到一个字符数据时调用该函数
32 {
33 echo $data;
34 }
35
36
37 xml_set_element_handler($parser,"start","stop"); //
指定元素处理器
38 xml_set_character_data_handler($parser,"char"); //
指定字符数据处理器
39
40 $fp=fopen("17-1.xml","r"); //
打开XML
文件
41 while($data=fread($fp,1024)) //
循环读入XML
文件中的内容
42 {
43 xml_parse($parser,$data,feof($fp)) or
44 die(sprintf("XML
错误: %s at line %d",
45 xml_error_string(xml_get_error_code($parser)),
46 xml_get_current_line_number($parser)));
47 }
48
49 xml_parser_free($parser); //
释放XML
分析器资源
50 ?>

图17-7 使用Expat函数处理XML文档的输出结果
【代码解析】下面对代码17-2的各个关键点加以解释。代码第02行使用函数xml_parser_create()初始化一个XML分析器。代码第04行建立函数star()用来当XML分析器找到一个元素开始时调用,这个函数内部通过判断作为参数传入的元素名称,来显示不同的文字。注意,判断元素名称时,元素名称用大写字母,无论XML文档中使用的是否是大写或小写字母。代码第26行定义函数stop()在一个元素结束时调用,该函数仅仅用来向页面输出换行。代码第31行定义函数char()在XML分析器找到一个字符数据是调用,该函数向页面输出这个字符数据。
接下来的代码就是实际的PHP处理XML函数。代码第37行使用函数xml_set_element_handler()指定元素处理器,其第2个参数就是代码第4行定义函数的名称start,以字符串形式传入函数xml_set_element_handler();第3个参数就是第26行定义的函数名称stop,同样是以字符串形式将函数名称“stop”传入函数xml_set_element_handler()。这样,当函数xml_set_element_handler()在处理XML元素开始和结束部分的时候就会分别调用程序自定义的函数start()和stop()。
代码第38行使用函数xml_set_character_data_handler()指定字符数据的XML处理器。同理,该函数也使用了自定义函数char()的名称“char”作为其第2个参数,这样当分析到一个XML字符数据时,就会调用函数char()来输出该字符数据。
代码第40行使用函数fopen()打开XML文件17-1.xml,接着在第43行调用函数xml_parse()分析读入的XML数据。同时,在分析XML出现错误时调用函数xml_error_string()和xml_get_current_line_number()分别获取错误信息和错误所在行。代码最后使用函数xml_parser_free()释放程序开始建立的XML分析器实例。
上一篇:17.2深入认识XML文档
