如 今人人鼓吹XML是Web开发者最好的朋友(%$$#^64667*&%2)我型我塑www.5x54.com,有了XML的帮忙(%$$#^64667*&%2)我型我塑www.5x54.com,后者即可轻松地格式化和显示来自几乎任何数据源的数据。但是(%$$#^64667*&%2)我型我塑www.5x54.com,对动态内容而言(%$$#^64667*&%2)我型我塑www.5x54.com,格式优良的 数据却还远远谈不上达到理想状态。大多数的Web开发者都会告诉你(%$$#^64667*&%2)我型我塑www.5x54.com,今天的网络上没有动态内容怎么能行!问题是:“到底该如何用XML创建动态内容呢?”
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 答案是用动态内容处理语言来解析XML(%$$#^64667*&%2)我型我塑www.5x54.com,比如用PHP或者Perl等(%$$#^64667*&%2)我型我塑www.5x54.com,从理论上说(%$$#^64667*&%2)我型我塑www.5x54.com,这类程序语言是可以出于各种目的利用 XML的。无非是采用一些能解析XML的工具包而已。James Clark就提供了一种名叫expat的工具包。expat XML工具包用C语言解析 XML(%$$#^64667*&%2)我型我塑www.5x54.com,令PHP与XML轻松共舞。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com PHP是一种专为Web设计的绝佳脚本语言。XML是表示Web内容的标准。两者联手真是要多美有多美!
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 下面我会给读者演示一个简单的示例(%$$#^64667*&%2)我型我塑www.5x54.com,通过这个例子即可说明如何用PHP把XML文档解析为HTML。然后我会介绍一些PHP的其他XML概念。用PHP解 析 XML很简单(%$$#^64667*&%2)我型我塑www.5x54.com,操作起来很直观但却需要对细节有所解释。一旦真正掌握了应用的要领(%$$#^64667*&%2)我型我塑www.5x54.com,你肯定会惊奇自己怎么不早想到把它们俩拢一块儿来。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 概述
(%$$#^64667*&%2)我型我塑www.5x54.com PHP 用expat这种XML工具包(%$$#^64667*&%2)我型我塑www.5x54.com,通过C语言来解析XML。这个工具包的函数集同Perl XML解析所采用的函数集是一样的(%$$#^64667*&%2)我型我塑www.5x54.com,此外(%$$#^64667*&%2)我型我塑www.5x54.com,这种工具包还是事件驱动型的解析器。这就是说(%$$#^64667*&%2)我型我塑www.5x54.com,expat把每个XML标签或者新一行代码当作事件的起始(%$$#^64667*&%2)我型我塑www.5x54.com,而事 件就是函数的触发器。Expat的安装非常简单(%$$#^64667*&%2)我型我塑www.5x54.com,如果你正在用着 Apache Web服务器(%$$#^64667*&%2)我型我塑www.5x54.com,那么你可以在PHP XML参考页上找到安装和下载指南。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 用PHP解析XML的基本任务是这样的:首先(%$$#^64667*&%2)我型我塑www.5x54.com,创建XML解析器的一个实例。接着(%$$#^64667*&%2)我型我塑www.5x54.com,定义处理触发事件的函数(%$$#^64667*&%2)我型我塑www.5x54.com,比如开始或者结束标签等。随后(%$$#^64667*&%2)我型我塑www.5x54.com,定义实际意义的数据处理程序。最后(%$$#^64667*&%2)我型我塑www.5x54.com,打开XML文件(%$$#^64667*&%2)我型我塑www.5x54.com,读取文件数据并解析数据。之后关闭文件释放XML解析器。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 你瞧(%$$#^64667*&%2)我型我塑www.5x54.com,就像我说的那样(%$$#^64667*&%2)我型我塑www.5x54.com,这套操作过程没什么特别的。不过(%$$#^64667*&%2)我型我塑www.5x54.com,在我们讨论具体的示例之前先了解以下的一些警示:
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com Expat不对XML进行检验。这意味着只要XML文件格式正确——所有的元素嵌套得当、开始和关闭标签没有任何错误——它就会被解析。Expat可不管XML是否遵守XML文件头中引用的标准或者定义。
(%$$#^64667*&%2)我型我塑www.5x54.com Expat把XML标签全部转换为大写字母。如果你的脚本在标签名和其他内容上大小写字母混用可就要小心了。
(%$$#^64667*&%2)我型我塑www.5x54.com PHP是在magic quotes设置启用的情况下编译而成(%$$#^64667*&%2)我型我塑www.5x54.com,那么复杂的XML文件不会得到正确的解析。要是magic quotes不是默认设置(%$$#^64667*&%2)我型我塑www.5x54.com,你就当我没说。
(%$$#^64667*&%2)我型我塑www.5x54.com 好了(%$$#^64667*&%2)我型我塑www.5x54.com,我们现在就来看看有关的示例!
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 基本示例
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 为了把复杂的事情简单化(%$$#^64667*&%2)我型我塑www.5x54.com,我在例子中省略了错误检查和其他一些不必要的东西(%$$#^64667*&%2)我型我塑www.5x54.com,当然(%$$#^64667*&%2)我型我塑www.5x54.com,你可以在自己的代码随心所欲。我假定你早就熟悉PHP及其语法(%$$#^64667*&%2)我型我塑www.5x54.com,而我会对XML函数做一番解释。首先我会说明脚本程序的含义(%$$#^64667*&%2)我型我塑www.5x54.com,接着定义用户定义函数(%$$#^64667*&%2)我型我塑www.5x54.com,实际上这些函数位于引用它们的代码之前。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 所示为脚本的完整代码:
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 程序代码
(%$$#^64667*&%2)我型我塑www.5x54.com
|
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 脚本要解析的XML文档则是
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 程序代码
(%$$#^64667*&%2)我型我塑www.5x54.com
|
(%$$#^64667*&%2)我型我塑www.5x54.com 首先我创建了XML解析器的一个实例:
(%$$#^64667*&%2)我型我塑www.5x54.com $parser = xml_parser_create();
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 接着(%$$#^64667*&%2)我型我塑www.5x54.com,我定义解析器遭遇开始和结束标签时的操作。注意“startElement”和“endElement”是用户定义的函数(%$$#^64667*&%2)我型我塑www.5x54.com,当然你可以按照自己的喜好给它们起个其他名字(%$$#^64667*&%2)我型我塑www.5x54.com,但我起的这些名字可是标准的习惯要求。
(%$$#^64667*&%2)我型我塑www.5x54.com xml_set_element_handler($parser, “startElement”, “endElement”);
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 然后我定义了数据操作。这里的“characterData”也是用户定义的函数(%$$#^64667*&%2)我型我塑www.5x54.com,名字也是习惯性的。
(%$$#^64667*&%2)我型我塑www.5x54.com xml_set_character_data_handler($parser, “characterData”);
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 现在打开文件读取数据。你可以在这里开始编写错误处理代码(%$$#^64667*&%2)我型我塑www.5x54.com,我在例子中省略了这些错误处理。不要忘了在脚本的开头定义$xml_file。
(%$$#^64667*&%2)我型我塑www.5x54.com $filehandler = fopen($xml_file, “r”);
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 我开始读取文件内容(%$$#^64667*&%2)我型我塑www.5x54.com,一次读4K字节并放在变量“$data”内直到文件末尾。我用xml_parse解析读取的这些数据段。
(%$$#^64667*&%2)我型我塑www.5x54.com while ($data = fread($filehandler, 4096)) {
(%$$#^64667*&%2)我型我塑www.5x54.com xml_parse($parser, $data, feof($filehandler));
(%$$#^64667*&%2)我型我塑www.5x54.com }
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 最后进行清空、关闭文件和释放解析器等操作。
(%$$#^64667*&%2)我型我塑www.5x54.com fclose($filehandler);
(%$$#^64667*&%2)我型我塑www.5x54.com xml_parser_free($parser);
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 以上就是脚本中所用到的所有XML函数(%$$#^64667*&%2)我型我塑www.5x54.com,下面我再具体解释下其中用到的3个用户定义函数(%$$#^64667*&%2)我型我塑www.5x54.com,它们就是“startElement”、“endElement”和“characterData”。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 只要xml_parse遇到<url>这样的开始标签(%$$#^64667*&%2)我型我塑www.5x54.com,“startElement”函数就由XML解析器调用(%$$#^64667*&%2)我型我塑www.5x54.com,在我们的例子中解析器就是$ parser。该函数是必须定义的函数(%$$#^64667*&%2)我型我塑www.5x54.com,它拥有3个自动传递给它的参数:XML解析器实例、大写的元素名称(%$$#^64667*&%2)我型我塑www.5x54.com,比如URL以及该元素所具有的属性数组。在以 上示例中(%$$#^64667*&%2)我型我塑www.5x54.com,XML文件中的元素没有属性集合(%$$#^64667*&%2)我型我塑www.5x54.com,所以数组参数为空(%$$#^64667*&%2)我型我塑www.5x54.com,但这个参数还是必须存在的。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 就这个例子而言(%$$#^64667*&%2)我型我塑www.5x54.com,我决定在一个HTML表中显示我的XML数据。如上所示(%$$#^64667*&%2)我型我塑www.5x54.com,出于简化的缘故我没有编写错误处理代码。这里我耍了个障眼法(%$$#^64667*&%2)我型我塑www.5x54.com,因为我知道XML 文件中标签出现的顺序。否则我可以用 “startElement”、“characterData”和“endElement”函数来定义数组(%$$#^64667*&%2)我型我塑www.5x54.com,然后用单独的函数显示结果。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com function startElement($parser_instance, $element_name, $attrs) {
(%$$#^64667*&%2)我型我塑www.5x54.com switch($element_name) {
(%$$#^64667*&%2)我型我塑www.5x54.com case “URL” : echo “<tr><td><a href=\””;
(%$$#^64667*&%2)我型我塑www.5x54.com break;
(%$$#^64667*&%2)我型我塑www.5x54.com case “SUMMARY” : echo “<td>”;
(%$$#^64667*&%2)我型我塑www.5x54.com break;
(%$$#^64667*&%2)我型我塑www.5x54.com }
(%$$#^64667*&%2)我型我塑www.5x54.com }
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 处理元素标签之后(%$$#^64667*&%2)我型我塑www.5x54.com,xml_parse一旦遇到XML数据就会调用“characterData”函数。这个函数也是由解析器自动调用的(%$$#^64667*&%2)我型我塑www.5x54.com,该函数需要两个参数(%$$#^64667*&%2)我型我塑www.5x54.com,解析器实例和包含数据的字符串。
(%$$#^64667*&%2)我型我塑www.5x54.com function characterData($parser_instance, $xml_data) {
(%$$#^64667*&%2)我型我塑www.5x54.com echo $xml_data;
(%$$#^64667*&%2)我型我塑www.5x54.com }
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 最后xml_parse遭遇结束标签(%$$#^64667*&%2)我型我塑www.5x54.com,运行“endElement”函数(%$$#^64667*&%2)我型我塑www.5x54.com,该函数带两个参数(%$$#^64667*&%2)我型我塑www.5x54.com,解析器实例和元素名称。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com function endElement($parser_instance, $element_name) {
(%$$#^64667*&%2)我型我塑www.5x54.com switch($element_name) {
(%$$#^64667*&%2)我型我塑www.5x54.com case “URL” : echo “\”>”;
(%$$#^64667*&%2)我型我塑www.5x54.com break;
(%$$#^64667*&%2)我型我塑www.5x54.com case “TITLE” : echo “</a></td>”;
(%$$#^64667*&%2)我型我塑www.5x54.com break;
(%$$#^64667*&%2)我型我塑www.5x54.com case “SUMMARY” : echo “</td></tr>”;
(%$$#^64667*&%2)我型我塑www.5x54.com break;
(%$$#^64667*&%2)我型我塑www.5x54.com }
(%$$#^64667*&%2)我型我塑www.5x54.com }
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 用PHP解析XML的轻量锻炼到这里就结束了(%$$#^64667*&%2)我型我塑www.5x54.com,下面我们开始加些重活。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 增加函数
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com PHP中还有其他一些同XML解析有关的函数。PHP.net文档对这些函数进行了完整的说明。我在这里提到了一些(%$$#^64667*&%2)我型我塑www.5x54.com,你或许不久就会用到这些函数:
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com xml_set_default_handler()—该函数的工作方式和xml_set_character_data_handler()函数相近(%$$#^64667*&%2)我型我塑www.5x54.com,但它捕获定义的一切。这个函数常用于文档类型声明控制数据的处理。
(%$$#^64667*&%2)我型我塑www.5x54.com xml_parser_set_option()—你可以用这个函数禁用字母的转大写操作或者选择其他替代的字符编码集。
(%$$#^64667*&%2)我型我塑www.5x54.com xml_parse_into_struct()—这个函数用来略过“startElement”、“characterData”和“endElement”函数的调用(%$$#^64667*&%2)我型我塑www.5x54.com,而把数据直接放进数组。
(%$$#^64667*&%2)我型我塑www.5x54.com xml_error_string()—这个函数用来从xml_parser() 错误中获取文本信息。
(%$$#^64667*&%2)我型我塑www.5x54.com xml_get_error_code ()—你可以用这个函数获取上面提到的错误字符串。后两个函数的用法是这样的:if(!xml_parse($parser, $data, feof ($filehandler))) { die(xml_error_string(xml_get_error_code($parser)); )
(%$$#^64667*&%2)我型我塑www.5x54.com 如果你觉得自己已经上手(%$$#^64667*&%2)我型我塑www.5x54.com,我建议你仔细读读PHP手册页中提供的XML External Entity Example。这些例子提出了本文没有提到的其他一些概念以及处理文件错误的某些技术。
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com
(%$$#^64667*&%2)我型我塑www.5x54.com 小结
(%$$#^64667*&%2)我型我塑www.5x54.com 本文演示了PHP和XML的紧密结合过程。两种技术以Web为中心的天性促使它们联合起来成为动态内容所需的理想解决方案。
|