第33章 使用XML和SOAP来连接Web服务

在最近几年中,XML(可扩展的置标语言)已经成为通信的重要方法。在本章中,我们使用亚马逊公司最新的Web服务接口在本地Web站点中创建一个以Amazon为后台的购物车(我们将这个应用程序命名为Tahuayo,它是亚马逊河区印第安人的名称)。我们将使用两种不同的方法来创建购物车:SOAP和REST。REST也就是基于HTTP协议之上的XML。我们将使用PHP内置的SimpleXML库和NuSOAP库来实现这两种方法。

在本章中,我们将主要介绍以下内容:

■理解XML和Web服务的基础知识

■使用XML与Amazon进行交互

■使用PHP的SimpleXML库解析XML

■缓存响应

■使用NuSOAP与Amazon进行交互

33.1 项目概述:使用XML和Web服务

在这个项目中,我们要实现两个目标:第一,理解什么是XML和SOAP并且掌握如何在PHP中使用它们。第二,使用这两种技术与外界进行通信。我们之所以选择Amazon的Web服务程序作为例子,是因为它对我们自己的Web站点将会非常有帮助。

很早以前,Amazon就提供了允许在Web站点给其产品做广告的相关程序。用户可以点击这些链接进入到Amazon站点上每一个产品的页面。如果某些用户通过某站点访问Amazon站点并且成功购买其产品,该站点将获得一定的现金奖励。

Amazon的这些Web服务程序允许将它作为一个引擎:我们可以搜索Amazon站点并且通过自己的站点显示搜索结果,或者在用户浏览我们站点时将用户选择的产品直接放入购物车中。换句话说,客户在付费之前可以一直使用我们的站点,就像在Amazon站点上的购买操作一样。

我们和Amazon站点之间的交互可以按两种可能的方式进行。第一种方法是使用基于HTTP的XML,也就是表示状态转换(REST)。例如,如果我们希望使用这种方法执行一个搜索操作,可以向Amazon发送一个关于所查询信息的普通HTTP请求,Amazon将用包含请求信息的XML文档响应查询。于是,我们可以使用PHP的XML库对这个XML文档进行解析并且使用我们所选择的接口向终端用户显示搜索结果。通过HTTP发送和接收数据的过程非常简单,但是解析结果文档的难易程度则是由文档的复杂度决定的。

第二种方法是使用SOAP。SOAP是Web服务的标准协议之一。它是简单对象访问协议的缩写,但是最近该协议变得不再简单,因此其名称就有一点名不符实。最后的结果是该协议仍然叫做SOAP,但是它不再是一个缩写词了。

在这个项目中,我们将创建一个可以向Amazon SOAP服务器发送请求并获得响应的SOAP客户端。这些将包含我们使用基于HTTP的XML方法从Amazon服务器获得的响应信息相同的信息,但是我们将使用不同的方法来获取数据,也就是NuSOAP库。

在这个项目中,我们最终的目标是创建自己的、使用Amazon作为后台的图书销售Web站点。我们将创建两个版本:一个是使用REST,而另一个是使用SOAP。

在真正进入这个项目之前,我们需要熟悉XML和Web服务的常规结构和使用。

33.1.1 理解XML

下面,如果我们不熟悉XML和Web服务的概念,那么花一些时间来了解它们。

正如前面已经提到的,XML是可扩展的置标语言。在W3C的站点上,提供了其规范。在W3C的XML站点上,可以找到大量关于XML的信息。W3C的XML站点URL如下所示:http://www.w3.org/XML/。

XML源自SGML(标准通用置标语言)。如果我们已经了解了HTML(假设我们的确已经了解了),这对快速理解XML概念是非常有帮助的。

XML是针对文档的,基于标记的文本格式。作为XML文档的一个例子,程序清单33-1给出了Amazon站点返回的、针对一个基于特定请求参数的HTTP XML请求的响应内容。

程序清单33-1 描述了本书第一版的XML文档


<?xml version="1.0"encoding="UTF-8"?>

<ItemLookupResponse

xmlns="http://webservices.amazon.com/AWSECommerceService/2005-03-23">

<Items>

<Request>

<IsValid>True</IsValid>

<ItemLookupRequest>

<IdType>ASIN</IdType>

<ItemId>0672317842</ItemId>

<ResponseGroup>Similarities</ResponseGroup>

<ResponseGroup>Small</ResponseGroup>

</ItemLookupRequest>

</Request>

<Item>

<ASIN>0672317842</ASIN>

<DetailPageURL>http://www.amazon.com/PHP-MySQL-Development-Luke-Welling/

dp/0672317842%3F%26linkCode%3Dsp1%26camp%3D2025%26creative%3D165953%26crea

tiveASIN%3D0672317842

</DetailPageURL>

<ItemAttributes>

<Author>Luke Welling</Author>

<Author>Laura Thomson</Author>

<Manufacturer>Sams</Manufacturer>

<ProductGroup>Book</ProductGroup>

<Title>PHP and MySQL Web Development</Title>

</ItemAttributes>

<SimilarProducts>

<SimilarProduct>

<ASIN>1590598628</ASIN>

<Title>Beginning PHP and MySQL:From Novice to Professional,

Third Edition(Beginning from Novice to Professional)</Title>

</SimilarProduct>

<SimilarProduct>

<ASIN>032152599X</ASIN>

<Title>PHP 6 and MySQL 5 for Dynamic Web Sites:

Visual QuickPro Guide</Title>

</SimilarProduct>

<SimilarProduct>

<ASIN>B00005UL4F</ASIN>

<Title>JavaScript Definitive Guide</Title>

</SimilarProduct>

<SimilarProduct>

<ASIN>1590596145</ASIN>

<Title>CSS Mastery:Advanced Web Standards Solutions</Title>

</SimilarProduct>

<SimilarProduct>

<ASIN>0596005431</ASIN>

<Title>Web Database Applications with PHP&MySQL,

2nd Edition</Title>

</SimilarProduct>

</SimilarProducts>

</Item>

</Items>


该文档是以如下语句行为开始的:


<?xml version="1.0"encoding="UTF-8"?>


这是一个标准的声明,它告诉我们接下来的文档将会是使用UTF-8字符编码的XML。

让我们看看该文档的正文。整个文档由打开和关闭的标记对组成,例如,你可以从以下代码的开放和关闭的Item标记看到:


<Item>


</Item>是一个元素,就像其在HTML中一样。而且,就像在HTML中,我们可以嵌套元素,例如,以上代码的ItemAttributes元素,它为Item元素内,同样,Author元素却位于ItemAttributes元素内:


<ItemAttributes>

<Author>Luke Welling</Author>

<Author>Laura Thomson</Author>

<Manufacturer>Sams</Manufacturer>

<ProductGroup>Book</ProductGroup>

<Title>PHP and MySQL Web Development</Title>


还像HTML中的一样,元素可以具有属性。就像这个例子中,例如:

Details元素只有一个属性url。由于URL非常长,在这里,它被分成了3行。

当然,XML和HTML还是有一些不同的。首先,在XML中,所有开始的标记都必须有一个对应的结束标记。这条规则的例外就是空元素,空元素的开始和结束标记都在一个标记内,因为它没有包括任何文本。如果我们熟悉XHTML,将会看到,我们可以在使用<br>的地方使用<br/>标记。此外,所有元素必须正确地嵌套。在HTML解析器中,<b><i>Text</b></i>可能是合法的,但是在XML或XHTML中,它却是不合法的,这些标记必须正确地嵌套,<b><i>Text</i></b>。

注意XML和HTML之间最主要的区别在于我们可以在文档中设置自己的标记!这就是XML的灵活性。我们可以根据希望保存的数据来设计文档的结构。我们可以通过编写一个DTD(文档类型定义)或XML模式来规范化XML文档的结构。这两个文档都是用来描述一个给定的XML文档的结构。如果你愿意,我们可以将DTD或模式看作是一个类声明,而XML文档则是类的实例。在这个例子中,没有使用DTD或模式。

可以通过如下URL给出的Web服务查阅Amazon站点的XML模式:http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.xsd。

你应该可以直接在浏览器中打开这个XML模式。

需要注意的是,除了最初的XML声明外,文档的所有正文都是包含在ItemLookupResponse元素中。这个元素就叫做该文档的根元素。下面,我们仔细查看这个元素:


<ItemLookupResponse

xmlns="http://webservices.amazon.com/AWSECommerceService/2005-03-23">


该元素具有一些特殊的属性。这些属性是XML的名称空间(namespace)。我们并不需要理解名称空间,因为在这个项目中,这并不重要,但是这将会是非常有用的。该元素的基本功能是确保元素和属性名称的正确性,这样当处理来自不同组织的文档时,这些通用名称不会相互冲突。

如果想要了解更多关于名称空间的内容,可以在如下URL找到“XML标准建议的名称空间”文档:http://www.w3.org/TR/REC-xml-names/。

如果想要了解更多关于XML的内容,在Internet上存在了大量的资料。W3C站点就是了解XML的一个非常不错的入门站点,在该站点上,介绍了关于XML和Web入门的海量图书。ZVON.org提供了关于XML的最佳入门教程。