用PHP解析XML

用PHP解析XML 作者:zishu 
 

如今人人鼓吹XML是Web开发者最好的朋友,有了XML的帮忙,后者即可轻松地格式化和显示来自几乎任何数据源的数据。但是,对动态内容而言,格式优良的数据却还远远谈不上达到理想状态。大多数的Web开发者都会告诉你,今天的网络上没有动态内容怎么能行!问题是:“到底该如何用XML创建动态内容呢?” 


答案是用动态内容处理语言来解析XML,比如用PHP或者Perl等,从理论上说,这类程序语言是可以出于各种目的利用XML的。无非是采用一些能解析XML的工具包而已。James Clark就提供了一种名叫expat的工具包。expat XML工具包用C语言解析XML,令PHP与XML轻松共舞。

PHP是一种专为Web设计的绝佳脚本语言。XML是表示Web内容的标准。两者联手真是要多美有多美! 

下面我会给读者演示一个简单的示例,通过这个例子即可说明如何用PHP把XML文档解析为HTML。然后我会介绍一些PHP的其他XML概念。用PHP解析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_file = "data.xml";
echo "<table border=0 cellpadding=5>"; echo "<tr><th colspan=2>XML Articles</th></tr>";
function startElement($parser_instance, $element_name, $attrs) {    switch($element_name) {        case "URL"     :    echo "<tr><td><a href=/"";                            break;        case "SUMMARY" :    echo "<td>";                            break;    } }
function characterData($parser_instance, $xml_data) {    echo $xml_data; }
 
function endElement($parser_instance, $element_name) {    switch($element_name) {        case "URL"     :    echo "/">";                            break;        case "TITLE"   :    echo "</a></td>";                            break;        case "SUMMARY" :    echo "</td></tr>";                            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 "</table>";
?>


脚本要解析的XML文档则是 

 程序代码

<?xml version="1.0" encoding="utf-8"?>
<series>      <article>             <url>http://builder.com.com/article.jhtml?id=u00220020327adm01.htm</url>              <title>Remedial XML for programmers: Basic syntax</title>              <summary>In this first installment in a three-part series, I'll introduce you to XML and its basic syntax.</summary>       </article>       <article>             <url>http://builder.com.com/article.jhtml?id=u00220020401adm01.htm</url>              <title>Remedial XML: Enforcing document formats with DTDs</title>              <summary>To enforce structure requirements for an XML document, you have to turn to one of XML's attendant technologies, data type definition (DTD).</summary>       </article>       <article>             <url>http://builder.com.com/article.jhtml?id=u00320020418adm01.htm</url>              <title>Remedial XML: Using XML Schema</title>              <summary>In this article, we'll briefly touch on the shortcomings of DTDs and discuss the basics of a newer, more powerful standard: XML Schemas.</summary>       </article>       <article>             <url>http://builder.com.com/article.jhtml?id=u00220020522adm01.htm</url>              <title>Remedial XML: Say hello to DOM</title>              <summary>Now it's time to put on your programmer's hat and get acquainted with Document Object Model (DOM), which provides easy access to XML documents via a tree-like set of objects.</summary>       </article>       <article>             <url>http://builder.com.com/article.jhtml?id=u00220020527adm01.htm</url>              <title>Remedial XML: Learning to play SAX</title>              <summary>In this fifth installment in our Remedial XML series, I'll introduce you to the SAX API and provide some links to SAX implementations in several languages.</summary>       </article> </series>


首先我创建了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遇到<url>这样的开始标签,“startElement”函数就由XML解析器调用,在我们的例子中解析器就是$parser。该函数是必须定义的函数,它拥有3个自动传递给它的参数:XML解析器实例、大写的元素名称,比如URL以及该元素所具有的属性数组。在以上示例中,XML文件中的元素没有属性集合,所以数组参数为空,但这个参数还是必须存在的。

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

function startElement($parser_instance, $element_name, $attrs) {
    switch($element_name) {
        case “URL”     :    echo “<tr><td><a href=/””;
                            break;
        case “SUMMARY” :    echo “<td>”;
                            break;
    }
}


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

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

function endElement($parser_instance, $element_name) {
    switch($element_name) {
        case “URL”     :    echo “/”>”;
                            break;
        case “TITLE”   :    echo “</a></td>”;
                            break;
        case “SUMMARY” :    echo “</td></tr>”;
                            break;
   }
}


用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为中心的天性促使它们联合起来成为动态内容所需的理想解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值