此页面是"Adam A Flynn"编写的"XMLParser Documentation/Tutorial"的简体中文版本,如无特殊说明,下文中的"我"均指"Adam A Flynn"。译文如有不当之处,敬请指正。 原文链接

获取XMLParser!

点击以下链接以获取XMLParser:
PHP 4
PHP 5

两者的最新版本均为1.3.0。 如果你的版本低于这个,请考虑升级。

更新日志

Version 1.3.0
注意:关于1.3.0所增加的新特性的文档还没有完成... 我会尽快添加!
  • 新增一个管理带破折号和冒号的标签的特性
  • 新增一个删除标签的特性
  • 修复一些其他问题
Version 1.2.0
  • 为命名冲突增加错误报告功能。
Version 1.1.0
Version 1.1.0 并完全向下兼容 Version 1.0.0。
  • 修正PHP4引用bug,该bug会导至解析器不能在PHP4下工作。重写了PHP4版本的栈系统。
  • 在XMLTag成员的名称前加上前缀'tag'以减少命名冲突的可能性。
Version 1.0.0
  • 第一个发行版本,我并不打算列出所有的特性。



使用XMLParser?

你正在使用XMLParser?很好。我希望它能很好地为你服务。因为,嗯,我们都知道软件并不能总是完美地工作,在使用XMLParser的时候你可能会需要一些帮助。如果你需要帮忙,尽管 发邮件给我 ,我会尽力帮你。

如果XMLParser确实在某些地方帮助了你,你也许会考虑提供一些捐赠。

XMLParser教程/文档

XMLParser是什么

XMLParser是我(Adam A Flynn)在花费了很大的工夫来处理PHP的XML扩展后设计的,因为一个客户需要这么个"能在PHP4和PHP5下都正确地工作"的东西。我最初的成果是一段段看起来就让人头疼的代码,而它们所做的工作,往往只用一行SimpleXML代码就能实现。为此,我决定在做下一个涉及XML的项目之前写一个能像SimpleXML一样工作的解析器,并且能够兼容PHP4和PHP5。这就是XMLParser。

这个解析器有两个版本(准确的说是两个文件,每个包含一个类)。一个用于PHP4,一个用于PHP5。两者提供了完全一致的接口,因此你只需编写一种代码来使用这个解析器──只要你根据PHP的版本包含相应版本的解析文件,你的代码就能在两个PHP版本中都正确地工作。

使用XMLParser

因为我希望我的解析器和SimpleXML相似(从它最初的设计开始便或多或少地模仿了SimpleXML──只不过用了PHP4的函数来进行实现),因此我选择了PHP官方网站的SimpleXML文档页面上所使用的一系列例子和XML文件来演示XMLParser。


我们的XML示例文件(example.xml)
<?xml version='1.0' standalone='yes' ?>
<movies>
<movie>
<title>PHP: Behind the Parser</title>
<characters>
<character>
<name>Ms. Coder</name>
<actor>Onlivia Actora</actor>
</character>
<character>
<name>Mr. Coder</name>
<actor>El Actor</actor>
</character>
</characters>
<plot>
So, this language. It's like, a programming language. Or is it a scripting language? All is revealed in this thrilling horror spoof of a documentary.
</plot>
<rating type="thumbs">7</rating>
<rating type="stars">5</rating>
</movie>
</movies>

入门

开始使用解析器之前,你需要加载你想操作的XML文件。为此,我们将调用example.xml文件。和SimpleXML一样,XMLParser的构造函数将获取XML文件本身,而不仅仅是对其文件名的引用。这意味着在初始化XMLParser对象之前,我们需要使用file_get_contents()调用XML文件。

当我们完成了对XMLParser的调用并给它填充了一些数据,接下来,我们就要让它施展魔力,做一些实际的解析工作。完成这步只需要轻松地调用一下Parse方法。

配置解析器

<?php
//Get the XML document loaded into a variable
$xml file_get_contents('example.xml');
//Set up the parser object
$parser = new XMLParser($xml);

//Work the magic...
$parser->Parse();
?>


XML解析器包含一个错误处理函数,当对XML文档的解析出现问题时,它能触发一个PHP错误。这个函数叫trigger_error,是XMLParser类的一个方法。你能按照自己喜欢的方式自由地改变错误的显示方式;这些参数应该算是简单的。当然,如果我们的解析工作没有遇到问题,那么只管继续好了。

XMLParser对象的结构是非常简单明了的,当然,也需要花些时间来适应它。文档的根结点被包含在解析器的document成员中。也就是说在上面的例子中,$parser->document就是根标签,而不用去管这个标签的实际名称是什么。在根标签之下,每个子标签都被分配到一个以标签自身名称命名的数组中。按照上述规则,$parser->document->movie[0]指向第一个movie标签。$parser->document->movie是一个数组,而不是一个XMLTag对象。因此在大多数情况下,想通过$parser->document->movie来获取第一个movie对象是行不通的。

使用XMLParser

正如之前所说的,我们要按着SimpleXML文档的例子来进行演示,那么我们现在就回到SimpleXML的文档所用的例子。SimpleXML的示例2演示了输出第一个movie的plot,示例3演示了输出每个movie的plot。我将把示例2和示例3合并到下面这个例子中。这个例子的前提是你已经加载并解析了XML文档(参考前面的例子)。

获取<plot>

<?php
//Echo the plot of the first <movie>
echo $parser->document->movie[0]->plot[0]->tagData;

//Echo the plot of each <movie>
foreach($parser->document->movie as $movie)
{
    echo 
$movie->plot[0]->tagData;
}
?>


好吧, 我承认这语法看起来并不能像SimpleXML中的那么美。为了实现对PHP4的兼容,我不能使用__toString()函数来简化代码,毕竟,这个解析器最重要的目的就是实现对PHP4兼容。如果我们只想在PHP5的服务器中运行,那直接去看SimpleXML的文档就好了,而不必像现在这样来读我的这个"替代品"的文档,对吧?当然,如果你想要在PHP5版本的解析文件中通过__toString()方法实现输出标签的数据,尽管去做吧,但是对于这些例子,我能想象你所要走的是条漫长的道路。

那么,让我们分析一下上面的例子,首先,我们所做的是通过文档树找到我们所需要的plot对象,然后,我们将它的tagData成员输出。那么什么是tagData呢?tagData是PHP的XML解析器给定的字符数据(XML文档中所有标记符以外的内容,包括标记符之间的空格)。因为PHP解析XML文档看上去像是逐行进行的,所以这个值是级联的。在将数据送到tagData之前,我使用trim()函数。这过滤了空格和其他空白字符。因此,每个字符数据行的开头和结尾的空白字符已经被过滤了。假如你的软件在类似情况下出现bug,那么这就是原因了。

保留字

最后,在介绍属性(是的,这个解析器当然能处理属性)之前,有个小小的问题需要注意,为什么我要使用tagData这个名称而不是其他更短的名称呢。在版本1中,我使用了data做为字符数据这个成员的名称,因为它更短,更容易使用。然而,当我开始使用这个类之后,我注意到自己有好几次都用到一个叫做<data>的标签;同时,我也收到一些来自使用者的电子邮件,告诉我当用到叫做<data>的标签时会发生一些问题。当解析器试图为data数组增加成员或创建新数组时,这会导致一个问题,并返回一个PHP错误和一个不怎么准确的文档树。因此,为了修复了这个问题,我决定在版本1.1中重命名所有XMLTag类中的成员。它们都有前缀tag,因为我想不到任何一个人们非要将一个XML标签命名为<tagdata>或<tagattrs>不可的理由。如果,在某些非常偶然的情况下你需要使用下列名称中的一者做为XML标签的名称时,那么你可以选择a)不要这么做,或者b)重命名XMLTag中的成员──用查找替换来重命名类中所有出现这个词的地方。保留字列表如下:
  • tagData
  • tagParents
  • tagChildren
  • tagAttrs
  • tagName

  • 属性

    属性非常容易使用。每个XMLTag对象都有一个关联数组成员叫做tagAttrs。在这个成员里面,键代表属性名称,而值代表属性值。我想我不必更进一步地深入讲解了,不过我将演示一个模仿SimpleXML的属性的例子。

    Accessing Attributes

    <?php
    //For each of the <rating> tags, display them
    foreach($parser->document->movie[0]->rating as $rating)
    {    
        
    //If the rating is in stars...
        
    if($rating->tagAttrs['type'] == 'stars')
            echo 
    $rating->tagData.' stars';

        
    //If the rating is in thumbs...
        
    if($rating->tagAttrs['type'] == 'thumbs')
            echo 
    $rating->tagData.' thumbs up';
    }
    ?>


    如你所见,属性可以从tagAttrs访问,字符数据则从tagData。非常简单,不是吗?

    值的设置与比较

    我们不会去依靠PHP5中的任何新的面向对象特性来使这个解析器更容易使用(再次声明,这是为了兼容PHP4),尽管使用这些特性能让值的设置和比较变的容易得多。在SimpleXML中,你需要进行强制类型转换才能像使用string类型一样使用它们。相比之下,在XMLParser中,你不必再进行类型转换。直接使用 = 或者 == 就能让程序很好的运作了。要确保你正在使用的是tagData,tagAttrs,或者其他的XMLTag成员。如果不是以上情况,那么就成了对一个对象进行字符串操作,这会导致一个PHP错误。

    XMLTag的其它成员

    如果你花了点时间看了源代码,那么你可能已经注意到XMLTag类中还有一些其他成员。它们的说明如下:

    成员说明
    tagChildren这个成员是一个数组,包含了对给定对象的所有直接子标签的引用,并以它们在XML中出现的顺序为序。这只是为通过名称访问子标签的方法提供了一种替代方案,并常被用在名称可以是任意的或者是未知的情况下。
    tagParents这个成员包含了这个对象到文档根标签为止的祖先标签数量。这个成员通常只用于决定要使用多少个标签来更好的格式化XML文档的输出。/td>
    tagName这个成员包含了当前标签的名称。同样,这也只用于解决XML文档的输出问题

    输出XML文档

    假如仅仅做到兼容PHP4和PHP5地对XML文档进行解析还不够的话,这个系统中还有一个函数来对XML文档进行输出。大多数情况下,这个函数仅仅是我用来确认这个系统能够解析整个XML树并且不必使用大量难以阅读的var_dump()声明,不过这个函数也能用来修改XML树并输出它,又或者是创建一个完全新的文档树,并得到它的XML文档。要访问这个函数,只需简单地输出XMLParser对象的GenerateXML()方法的返回值。就像下面所列的那么简单。

    输出XML文档
    <?php
    echo $parser->GenerateXML();
    ?>

    这段代码将从根标签开始对XML进行输出。如果你希望从文档树的更深处开始输出,你可以调用任何你想要的XMLTag对象的GetXML()方法。

    仍然需要帮助?

    如果这份文档无法给予你想要的帮助,你可以写电子邮件给我,我很乐意能帮你解决问题。