本章将介绍什么是WDDX,如何使用它,如何使用PHP的WDDX扩展。尽管WDDX本身不是web服务(web service),但可以利用它来创建web服务。
WDDX介绍
WDDX 是一项允许在保持数据完整性的前提下在系统格式中立的系统间交换数据和数据结构的XML技术。它定义了用来传送数据的XML结构,但它没有定义数据传输的机制;因此,WDDX本身不能被认为是一种web服务但却可以用来建立web服务,确切地说,你可以使用包括(并不限制于)HTTP,FTP,SMTP和 POP的任何一种传输类型。一般来说,你可以使用任何一种支持传输文本数据的协议。
背景
在1998 年,为了支持ColdFusion平台的分布式计算,Allaire创建了WDDX。利用WDDX,可以使变量(包括名称,数据类型和值)序列化成一个应用程序的XML文档,并且传送到另一个应用程序。作为接受方的应用程序可以反序列化XML文档并以变量原来的数据类型和值来重新建立这些变量。数据类型并不限于简单的数字和字符串类型,也可以包括一些复杂的数据结构,如数组(array),结构(structures)和记录集(recordsets)。
WDDX是一种与平台和语言无关的技术。这使得各种平台上的其它语言可以充分发挥它们的优点,因此,可以用一个平台上的某一种语言写的一个程序向另一个平台上的不同语言写的另一个程序发送数据。而接受数据的那个程序可以反序列化数据成具有其特性的变量类型。
WDDX并不是一个正式的标准,但它是建立在开放标准XML1.0之上的,可以自由使用和再发布。WDDX的发展和未来的进展已经被移至开放项目OpenWDDX(http://www.openwddx.org)上。尽管你可以在这个站点上找到一些信息和SDK,但你可能找不到过去几年有关于它的一些活动。这并不表明WDDX技术已经消亡。它在一些平台和语言上仍然很活跃,特别是PHP。
WDDX数据类型(WDDX Data Types)
想象一下PHP中的变量形式和数据类型,有个问题是,你如何利用XML将这些数据发送给另一个系统处理?例如,你可能有下面这个变量,需要将它的值发送到另一个系统:
$myinteger = 1;
使用XML,你可以将值序列号,也就是意味着将它们转换成文本:
<data>1</data>
这个数据对你来说可能已经足够了。它的缺点是你失去了原生的数据类型。当然,系统可能会有一些预定的结构可以相应地映射,或者可以在XML文档中作一些类型提示,如:
<data type='integer'>1</data>
这样就更加灵活了,但是交换数据的任一个系统都必须理解这种结构和知道如何去处理它。另一种解决方法是使用XML Schemas来提示数据类型,但是,系统同样需要知道如何处理这个文档。
WDDX提供了一种方法来解决这个问题。通过它的通用格式,该值可以序列化成如下格式:
<wddxPacket version="1.0">
<header/>
<data>
<number>1</number>
</data>
</wddxPacket>
在处理单一值时,这种格式可以接受,而XML是一种描述性的语言。从这个文档你可以知道,它包含有1。你可能从未使用这种格式来传送多个值,因为没有任何描述性的东西将它们区分开。大多数情况下,需要序列化的是包含描述性信息的变量而不单单是值。比如,要序列化下面的变量:
$mystring = ‘Text Data’;
$myinteger = 1;
<wddxPacket version="1.0">
<header/>
<data>
<struct>
<var name="mystring">
<string>Text Data</string>
</var>
<var name="myinteger">
<number>1</number>
</var>
</struct>
</data>
</wddxPacket>
这个结构清楚地显示了它包含了一个名称为mystring的变量,它的值为Text Data并且类型为string;还包含了一个名称为myinteger,值为1,类型为number的变量。WDDX并不之限制于这些简单的类型;它还支持多种语言中的多种抽象类型。如Talbe 15-1所示。
理解WDDX的结构
WDDX文档的结构自从1999年发布的WDDX1.0以来一直没有改变。尽管基于DTD(http://www.openwddx.org/downloads/download.cfm)的结构看起来很简单,实际上,文档的复杂度是由被序列化的数据决定的。变量的结构越复杂(例如多维数组或类),WDDX的文档也就越复杂。接下来几节将讲述WDDX文档的结构;你可以使用DOM或XMLWriter来创建它们,或者使用PHP的wddx扩展来创建。
WDDX Packets
使用WDDX的数据交换是通过数据包(packets)发生的。数据包是使用WDDX格式传送的XML文档数据,以wddxPacket元素开头。这个文档元素包含一个header元素和一个data元素,分别给注释(comments or notes)和要交换的实际数据提供了一个容器。文档元素同时还包含一个指示所使用的WDDX版本的属性version,因为目前只存在一个版本,因此该属性的值通常为1.0。可以使用comment元素作为header元素的子元素;否则header元素只是一个空的元素。例如:
<!-- Packet without notes or comments -->
<wddxPacket version='1.0'>
<header/>
<data>
<!-- WDDX data goes here -->
</wddxPacket>
<!-- Packet with a comment -->
<wddxPacket version='1.0'>
<header>
<comment>
This packet contains a comment
</comment>
</header>
<data>
<!-- WDDX data goes here -->
</wddxPacket>
data元素用来容纳要交换的数据。它是一个由被添加到数据包中的数据决定的单元。下面列出了data元素的一些有效的子元素,将在下一节介绍这些元素:
• null
• boolean
• number
• dateTime
• string
• array
• struct
• recordset
• binary
简单数据类型元素(Simple Data Type Elements)
简单数据类型是一些不能容纳附加的数据类型作为其内容的简单结构。这些元素包括null,boolean,number,dataTime和string。这些数据类型只能容纳一个特定类型的值作为其内容,当数据类型没有或者不能包含一个值时可以留空,比如NULL。
null
在支持NULL类型的语言里,null元素用来表示一个NULL值或者一个空字符串。PHP是支持NULL类型的,要记住的是如果和用另一种语言写的另一种系统交换数据,在反序列化时它可能会被解释成一个空字符串而不是NULL。这个元素的语法:
<null/>;
boolean
boolean元素用来表示布尔值。这个元素的值可以是true或false。大小写敏感在这里非常重要。这两个值必须是小写的,这样对于WDDX的DTD来说才是有效值。尽管有些情况下可以混合大小写,但强烈建议都使用小写。这个元素的语法:
<boolean>false</boolean>
number
number 元素是给浮点数用的。PHP设计到整数类型和浮点类型。The range of numbers for the value of this element is restricted to +/-1.7E+/-308 with the precision restricted to a maximum of 15 digits after the decimal point.This is comparable to an 8-byte floating-point representation, which is the common maximum value for floats within PHP.
语法示例:
<number>12345</number>
<number>-12345</number>
<number>12.345</number>
<number>-12.345</number>
<number>1.2345678901235E+014</number>
dateTime
dateTime 元素用来以ISO 8601格式传递日期和时间信息。尽管在PHP中没有dateTime类型,但这并不意味着你不能使用这个元素。比如,你可以在PHP5中将c作为格式参数传递给date()函数(如,date(’c')),或者在PHP5.1中将DATE_ISO8601作为参数传递给date()函数(如,date (DATE_ISO801))来创建一个ISO 8601格式的日期。这个元素的语法:
<dateTime>2005-10-08T17:28:04-04:00</dateTime>
string
string 元素可以容纳一个任意长度的字符串,但不能嵌入NULL。你可以用子元素char处理UTF-8编码的00-1F间的控制字符。char元素是一个附带有 code属性的空元素。该属性的值是一个十六进制的代码。在char元素中你不用处理制表符和换行符。这些特殊符号在XML文本内容中都是有效的。因此,如果给一个字符串值设定任意一个特殊的控制字符,string元素将包含混合内容。例如,XML会从XML数据中将回车移除,在Windows环境中,每一行的结尾都由一个回车和换行符组成。你可以使用char元素保留这些特殊字符。下面的例子描述了如何使用string和char元素:
<string>This is a string value without any control characters</string>
<string>Line 1<char code="0D"/><char code="0A"/>Line2</string>
复杂数据类型元素(Complex Data Type Elements)
复杂数据类型元素包括array,struct,recordset和binary元素。这些元素是给更复杂的数据结构使用的,不如PHP的数组和类。这些元素中只有array和struct两个元素可以直接与PHP原生类型映射。剩下的几个可以用程序转换成可使用的数据。
array
array元素用来保存一个基于数字索引的数组的数据。在PHP中,数组索引可以是数字或字符。只有数字索引的数组可以与array元素映射。字符索引可以使用struct元素处理。
注意:PHP中的数字索引是从0开始的。如果创建一个不是从0开始的数字索引,尽管它们还是数字索引的,但不能在array元素中使用。例如,数组 array(2=>’a', 4=>’b', 6=>’c')和数组array(0=>’a', 2=>’b')在使用wddx扩展序列化后将会产生一个有名称的变量的struct,而不是一个array元素。
array 元素的子元素的值可以是简单的或复杂的数据类型,这表明array元素可以有一个或多个数据类型的子元素,这些元素都是data元素中的有效元素。 array元素有一个名为length的属性。这个属性的值是数组中值的数量。在PHP中,在序列化时,length属性的值可以在数组上调用count ()函数获得。
下面两个数组都用从0开始的数字索引,可以像如下代码序列化成WDDX的array结构:
array(’a', 1, false);
array(0=>’a', 1=>1, 2=>false);
<array length='3'>
<string>a</string>
<number>1</number>
<boolean value='false'/>
</array>
struct
结构(stuctures)是使用字符索引的一个数据集合。在PHP中,结构(structures)属于字符索引的数组和对象。值得注意的是,任一一个非从0开始的索引数组或从0开始索引但索引数字不连续的数组将导致使用struct元素而不是array元素。
struct元素可以容纳0个或更多的var元素。这些元素使用name属性来描述变量或类的属性。每个var元素包括一个单一的子数据类型元素,这个元素与data或array元素的子元素是一致的。看一下PHP的变量:
$myint = 12345;
$mystring = “This is a string”;
$mykeys = array(’key1′=>1, ‘key2′=>2);
描述它们的var元素包含在struct元素中,这些结构如下:
<var name='myint'>
<number>12345</number>
</var>
<var name='mystring'>
<string>This is a string</string>
</var>
<var name='mykeys'>
<struct>
<var name='key1'>
<number>1</number>
</var>
<var name='key2'>
<number>2</number>
</var>
</struct>
</var>
正如你所看到的,$mykeys变量的序列化结果是一个复杂的数据结构。这个变量包含一个关联数组;因此,var元素不仅本身是struct的一个子元素,它还包含了一个struct元素。这个struct元素又包含了几个用来描述数组里面各个项的var元素。如果你记得定义一个WDDX结构并不复杂,但序列化后的文档可能会变得非常复杂这句话,你现在应该明白它的意思了。要序列化的结构的复杂度直接影响到了WDDX数据包的复杂度。看了“使用WDDX”那一节,在将一个对象序列化成WDDX结构后,你会更加清楚这一点。
PHP是一种大小写敏感的语言,因此语句$myVar = array(’key’=>1, ‘KEY’=>2);将生成一个有两个不同键(key和KEY)的关联数组。许多使用WDDX的语言并没有区分变量名或键名的大小写的不同。如果一个WDDX结构包含两个同名的变量,尽管它们的大小写不一样,在反序列化结构时将会使用最后一个变量的值。如果你序列化$myVar,结果可能是这样:
<struct>
<var name='myVar'>
<struct>
<var name='key'><number>1</number></var>
<var name='KEY'><number>2</number></var>
</struct>
</var>
</struct>
在使用PHP反序列化数据包时得到的$myVar变量会和$myVar的原始变量一样,但是如果将这个结构传送到一个用大小写不敏感的语言写的系统时,结果将是一个只有一个元素的关联数组,键名是key,对应的值是2。因为相同的名字,第一个值覆盖了第二个值。为了互用性,最好使用不同的识别名字,不要考虑大小写敏感。
(未完待续)
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/guoguo1980/archive/2008/05/12/2436342.aspx