在PHP4中用工具包expat解析XML文档

关于在PHP中解析XML文档,有很多种方法,摘录:
1  php5的dom解析
2  php4的expat解析
3 基于以上两种技术之一自行开发的类
4 类似插件式的增强工具

以上这些基本上都是基于php基础之上的,任何一种在特定环境下都可使用。性能上各有优缺点,以下对主要的基础方法进行比较(上述前两种方法)

dom方法:
 优点:  操作简单,使用方便,支持树
 缺点:  但对服务器性能要求较高,要求基于php5环境,php4下的dom与php5不可同日而语。其解析一个文件,内存使用会十倍于文件大小,且速度很慢,因此大型xml文件应望而却步。

 适用:  服务器php版本较新,性能好,xml文件体积不大。

EXPAT解析方法:
 优点:  解析文件占用内存小,速度快,如果单为解析xml成html,则内存占用几乎可以忽略,因可定制使用,因此灵活性较强
 缺点:  操作不够简便,对新手而言不易掌握,无结构,虽可在需要的时候人工生成树,但相对困难。对文件的操作完全依赖于文件操作方法,本身对文件操作无支持。

 适用:  服务器版本低,性能差,对xml文件体积限制不大。(其解析内存耗用约2倍文件大小)

以上两种方法及其他基于此两种方法开发的类,大多也因以上两种基础上的原因,而各有优劣。
 当然,php5以后,又提供了一些新的操作xml的方法,但相信少有人用.

在PHP4中用工具包expat解析XML文档
概述:

PHP用expat这种XML工具包,通过C语言来解析XML。这个工具包的函数集同Perl XML解析所采用的函数集是一样的,此外,这种工具包还是事件驱动型的解析器。这就是说,expat把每个XML标签或者新一行代码当作事件的起始,而事件就是函数的触发器。Expat的安装非常简单,如果你正在用着Apache Web服务器,那么你可以在PHP XML参考页上找到安装和下载指南。

用PHP解析XML的基本任务是这样的:首先,创建XML解析器的一个实例。接着,定义处理触发事件的函数,比如开始或者结束标签等。随后,定义实际意义的数据处理程序。最后,打开XML文件,读取文件数据并解析数据。之后关闭文件释放XML解析器。

你瞧,就像我说的那样,这套操作过程没什么特别的。不过,在我们讨论具体的示例之前先了解以下的一些警示:

Expat不对XML进行检验。这意味着只要XML文件格式正确——所有的元素嵌套得当、开始和关闭标签没有任何错误——它就会被解析。Expat可不管XML是否遵守XML文件头中引用的标准或者定义。
Expat把XML标签全部转换为大写字母。如果你的脚本在标签名和其他内容上大小写字母混用可就要小心了。
PHP是在magic quotes设置启用的情况下编译而成,那么复杂的XML文件不会得到正确的解析。要是magic quotes不是默认设置,你就当我没说。
好了,我们现在就来看看有关的示例!

基本示例

为了把复杂的事情简单化,我在例子中省略了错误检查和其他一些不必要的东西,当然,你可以在自己的代码随心所欲。我假定你早就熟悉PHP及其语法,而我会对XML函数做一番解释。首先我会说明脚本程序的含义,接着定义用户定义函数,实际上这些函数位于引用它们的代码之前。
脚本要解析的XML文档代码:
[coolcode]

李宇春
24
张靓颖
22

[/coolcode]

脚本的完整代码:
[coolcode]
\n”;
echo “

\n”;
echo “\t

\n\t\t

\n\t

\n”;
echo “\t

\n\t\t

\n\t\t

\n\t\t

\n\t

\n”;
function startElement($parser_instance, $element_name, $attrs) {
switch($element_name) {
case “PERSON”:
echo “

\n\t\t

“;
break;
case “NAME”:
echo “

“;
break;
case “NAME” :
echo “

“;
break;
case “AGE” :
echo “

“;
break;
}
}

$parser = xml_parser_create();

xml_set_element_handler($parser, “startElement”, “endElement”);
xml_set_character_data_handler($parser, “characterData”);

if (!($filehandler = fopen($xml_file, “r”))) {
die(“could not open XML input”);
}

while ($data = fread($filehandler, 4096)) {
if (!xml_parse($parser, $data, feof($filehandler))) {
die(sprintf(“XML error: %s at line %d”,
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)));
}
}

fclose($filehandler);
xml_parser_free($parser);

echo “

个人资料
序号 姓名 年龄
“.$attrs[‘ID’].” “;
break;
case “AGE” :
echo “

“;
break;
}
}

function characterData($parser_instance, $xml_data) {
echo $xml_data;
}

function endElement($parser_instance, $element_name) {
switch($element_name) {
case “PERSON”:
echo “

“;

?>

[/coolcode]
处理之后的输出结果,观看演示

首先我创建了XML解析器的一个实例:
$parser = xml_parser_create();

接着,我定义解析器遭遇开始和结束标签时的操作。注意“startElement”和“endElement”是用户定义的函数,当然你可以按照自己的喜好给它们起个其他名字,但我起的这些名字可是标准的习惯要求。
xml_set_element_handler($parser, “startElement”, “endElement”);

然后我定义了数据操作。这里的“characterData”也是用户定义的函数,名字也是习惯性的。
xml_set_character_data_handler($parser, “characterData”);

现在打开文件读取数据。你可以在这里开始编写错误处理代码,我在例子中省略了这些错误处理。不要忘了在脚本的开头定义$xml_file。
$filehandler = fopen($xml_file, “r”);

我开始读取文件内容,一次读4K字节并放在变量“$data”内直到文件末尾。我用xml_parse解析读取的这些数据段。
while ($data = fread($filehandler, 4096)) {
    xml_parse($parser, $data, feof($filehandler));
}

最后进行清空、关闭文件和释放解析器等操作。
fclose($filehandler);
xml_parser_free($parser);

以上就是脚本中所用到的所有XML函数,下面我再具体解释下其中用到的3个用户定义函数,它们就是“startElement”、“endElement”和“characterData”。
只要xml_parse遇到这样的开始标签,“startElement”函数就由XML解析器调用,在我们的例子中解析器就是$parser。该函数是必须定义的函数,它拥有3个自动传递给它的参数:XML解析器实例、大写的元素名称,比如URL以及该元素所具有的属性数组。在以上示例中,XML文件中的元素没有属性集合,所以数组参数为空,但这个参数还是必须存在的。

就这个例子而言,我决定在一个HTML表中显示我的XML数据。如上所示,出于简化的缘故我没有编写错误处理代码。这里我耍了个障眼法,因为我知道XML文件中标签出现的顺序。否则我可以用“startElement”、“characterData”和“endElement”函数来定义数组,然后用单独的函数显示结果。
[coolcode]
function startElement($parser_instance, $element_name, $attrs) {
switch($element_name) {
case “URL” : echo “

”;
break;
}
}
[/coolcode]

 处理元素标签之后,xml_parse一旦遇到XML数据就会调用“characterData”函数。这个函数也是由解析器自动调用的,该函数需要两个参数,解析器实例和包含数据的字符串。
function characterData($parser_instance, $xml_data) {
    echo $xml_data;
}

最后xml_parse遭遇结束标签,运行“endElement”函数,该函数带两个参数,解析器实例和元素名称。

[coolcode]
function endElement($parser_instance, $element_name) {
switch($element_name) {
case “URL” : echo “\”>”;
break;
case “TITLE” : echo “

”;
break;
case “SUMMARY” : echo “

”;
break;
}
}
[/coolcode]

用PHP解析XML的轻量锻炼到这里就结束了,下面我们开始加些重活。

增加函数

PHP中还有其他一些同XML解析有关的函数。PHP.net文档对这些函数进行了完整的说明。我在这里提到了一些,你或许不久就会用到这些函数:

·  xml_set_default_handler()—该函数的工作方式和xml_set_character_data_handler()函数相近,但它捕获定义的一切。这个函数常用于文档类型声明控制数据的处理。

  • xml_parser_set_option()—你可以用这个函数禁用字母的转大写操作或者选择其他替代的字符编码集。
  • xml_parse_into_struct()—这个函数用来略过“startElement”、“characterData”和“endElement”函数的调用,而把数据直接放进数组。
  • xml_error_string()—这个函数用来从xml_parser() 错误中获取文本信息。
  • xml_get_error_code()—你可以用这个函数获取上面提到的错误字符串。后两个函数的用法是这样的:if(!xml_parse($parser, $data, feof($filehandler))) { die(xml_error_string(xml_get_error_code($parser)); )
  • 如果你觉得自己已经上手,我建议你仔细读读PHP手册页中提供的XML External Entity Example。这些例子提出了本文没有提到的其他一些概念以及处理文件错误的某些技术。

    小结

    本文演示了PHP和XML的紧密结合过程。两种技术以Web为中心的天性促使它们联合起来成为动态内容所需的理想解决方案。

    发表回复

    您的电子邮箱地址不会被公开。 必填项已用*标注

    此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据