本文考察了一些顶尖的XML模式,这些模式为各种各样的问题提供了解决方案,从基本的Web服务到数据描述等等。其中包括涉及到通讯录和发票的类似数据库的解决方案。本文选择模式的标准是根据其实用性和用途,及其在XML信息共享和交换方面对XML社区的影响。
简单对象访问协议(Simple Object Access Protocol,SOAP)实际上是一种Web服务技术,但Web服务中客户机和服务器之间的数据交换格式是通过灵活的XML模式实现的。
Web服务的主要优点是客户机和服务器通过网络进行信息和数据交换的互操作性的层次。SOAP标准使用XML以一种体系结构中立的格式来构造数据,定义数据类型和信息。
对于编程语言来说,只需要提供数据类型和需要在远程服务器上调用的函数名称即可。SOAP库将用主机语言编写的信息和格式转化成XML格式的消息,其中包括调用的函数和提供的参数。
通过W3C的例子就可以了解SOAP的结构。调用远程SOAP函数GetEndorsingBoarder()的时候,客户机上的调用程序生成清单1所示的XML消息。
清单1.调用远程SOAP函数GetEndorsingBoarder()
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <m:GetEndorsingBoarder xmlns:m="http://namespaces.snowboard-info.com"> <manufacturer>K2</manufacturer> <model>Fatbob</model> </m:GetEndorsingBoarder> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
SOAP客户机发送的整个消息都放在SOAP信封中。信封的内容就是消息的详细内容。
被调用的函数显然是GetEndorsingBoarder,它包括两个参数:manufacturer和model。由此可见,它把本地的可能采用二进制编码的字符串转化成了XML字符串。由于XML是平台独立的,主机使用SOAP系统不需要复杂的二进制编码和解码就可以交换消息。
服务器通过另一个XML编码的SOAP信封返回响应,这一次是函数的返回值。SOAP请求的响应格式与函数相同,只不过在信封内容的后面加上了Response,如清单2所示。
清单2. SOAP请求的响应
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <m:GetEndorsingBoarderResponse xmlns:m="http://namespaces.snowboard-info.com"> <endorsingBoarder>Chris Englesmann</endorsingBoarder> </m:GetEndorsingBoarderResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
通常不需要自己编写SOAP消息,SOAP库会自动生成。不过SOAP信封的结构和简单性表明使用SOAP标准共享信息很简单。
SOAP大大简化了交换消息和调用远程函数的工作。远程过程调用(Remote Procedure Call,RPC)标准需要复杂的方法来处理二进制数据的序列化,发送结构化更高的信息需要详细的声明和双向的信息转换。
使用SOAP,XML序列化大大降低了这种复杂性,使得跨平台、跨语言集成和数据交换更加简单。
Web服务描述语言(Web Services Description Language,WSDL)提供了一种描述Web服务(大多使用SOAP)的简单方法。WSDL允许您描述利用SOAP标准所提供的服务和接口。
比方说,可以创建描述某台服务器上提供的服务的WSDL文件,然后把该文件分发给需要这些服务的Web服务消费者。通过阅读和解析WSDL文件,消费者能够了解到使用这些Web服务需要知道的所有信息,包括可以交换的数据类型、参数以及返回的各种错误和其他信息。
再次使用来自W3C的例子,可以看到不同远程函数的声明和交换的数据都是通过结构的XML定义处理的,如清单3所示。
<?xml version="1.0"?>
<!-- root element wsdl:definitions defines set of related services --> <wsdl:definitions name="EndorsementSearch" targetNamespace="http://namespaces.snowboard-info.com" xmlns:es="http://www.snowboard-info.com/EndorsementSearch.wsdl" xmlns:esxsd="http://schemas.snowboard-info.com/EndorsementSearch.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<!-- wsdl:types encapsulates schema definitions of communication types; here using xsd --> <wsdl:types>
<!-- all type declarations are in a chunk of xsd --> <xsd:schema targetNamespace="http://namespaces.snowboard-info.com" xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<!-- xsd definition: GetEndorsingBoarder [manufacturer string, model string] --> <xsd:element name="GetEndorsingBoarder"> <xsd:complexType> <xsd:sequence> <xsd:element name="manufacturer" type="string"/> <xsd:element name="model" type="string"/> </xsd:sequence> </xsd:complexType> </xsd:element>
<!-- xsd definition: GetEndorsingBoarderResponse [... endorsingBoarder string ...] --> <xsd:element name="GetEndorsingBoarderResponse"> <xsd:complexType> <xsd:all> <xsd:element name="endorsingBoarder" type="string"/> </xsd:all> </xsd:complexType> </xsd:element>
<!-- xsd definition: GetEndorsingBoarderFault [... errorMessage string ...] --> <xsd:element name="GetEndorsingBoarderFault"> <xsd:complexType> <xsd:all> <xsd:element name="errorMessage" type="string"/> </xsd:all> </xsd:complexType> </xsd:element>
</xsd:schema> </wsdl:types>
<!-- wsdl:message elements describe potential transactions -->
<!-- request GetEndorsingBoarderRequest is of type GetEndorsingBoarder --> <wsdl:message name="GetEndorsingBoarderRequest"> <wsdl:part name="body" element="esxsd:GetEndorsingBoarder"/> </wsdl:message>
<!-- response GetEndorsingBoarderResponse is of type GetEndorsingBoarderResponse --> <wsdl:message name="GetEndorsingBoarderResponse"> <wsdl:part name="body" element="esxsd:GetEndorsingBoarderResponse"/> </wsdl:message>
<!-- wsdl:portType describes messages in an operation --> <wsdl:portType name="GetEndorsingBoarderPortType">
<!-- the value of wsdl:operation eludes me --> <wsdl:operation name="GetEndorsingBoarder"> <wsdl:input message="es:GetEndorsingBoarderRequest"/> <wsdl:output message="es:GetEndorsingBoarderResponse"/> <wsdl:fault message="es:GetEndorsingBoarderFault"/> </wsdl:operation> </wsdl:portType>
<!-- wsdl:binding states a serialization protocol for this service --> <wsdl:binding name="EndorsementSearchSoapBinding" type="es:GetEndorsingBoarderPortType">
<!-- leverage off soap:binding document style ...(no wsdl:foo pointing at the soap binding) --> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<!-- semi-opaque container of network transport details classed by soap:binding above ... --> <wsdl:operation name="GetEndorsingBoarder">
<!-- again bind to SOAP? ... --> <soap:operation soapAction="http://www.snowboard-info.com/ EndorsementSearch"/>
<!-- further specify that the messages in the wsdl:operation "GetEndorsingBoarder" use SOAP? ... --> <wsdl:input> <soap:body use="literal" namespace="http://schemas.snowboard-info.com/EndorsementSearch.xsd"/> </wsdl:input> <wsdl:output> <soap:body use="literal" namespace="http://schemas.snowboard-info.com/EndorsementSearch.xsd"/> </wsdl:output> <wsdl:fault> <soap:body use="literal" namespace="http://schemas.snowboard-info.com/EndorsementSearch.xsd"/> </wsdl:fault> </wsdl:operation> </wsdl:binding>
<!-- wsdl:service names a new service "EndorsementSearchService" --> <wsdl:service name="EndorsementSearchService"> <wsdl:documentation>snowboarding-info.com Endorsement Service</ wsdl:documentation>
<!-- connect it to the binding "EndorsementSearchSoapBinding" above --> <wsdl:port name="GetEndorsingBoarderPort" binding="es:EndorsementSearchSoapBinding">
<!-- give the binding an network address --> <soap:address location="http://www.snowboard-info.com/EndorsementSearch"/> </wsdl:port> </wsdl:service>
</wsdl:definitions>
|
WSDL声明了消息类型、默认数据类型和内容以及交换的数据结构。
访问服务器上SOAP结构需要使用的一切信息都可以在这个WSDL中找到。大多数语言和环境都提供一种阅读和解析WSDL的机制,以确定可用的函数和数据交换。
WSDL不仅定义了用于交换信息的SOAP接口,通过适当的WSDL生成程序,还可用于创建发送请求、生成并格式化响应所需要的代码。
语义Web(Semantic Web)和语义网格(Semantic Grid)技术都依赖于资源描述框架(Resource Description Framework,RDF)这种灵活的描述语言。RDF格式实际上是一个标准家族的成员之一。它用于描述信息和资源,使得系统很容易连接和关联不同的资源。
RDF是另一种经过W3C批准的标准,它用于定义信息和资源。RDF不需要XML,但一种用于描述信息的序列化格式采用了XML。
定义资源需要指定一个包含主语、谓词和宾语的表达式。比方说,如果描述一个网站的内容,主语就是该网站,谓词是“包含信息”,宾语就是内容的类型。建立该网站和其他资源的联系,可使用Friend of a Friend (FOAF)标记建立两个资源之间的链接。
RDF的目的是将关于资源和信息的自然语言的陈述转化为机器可解析的格式。比如可将The MCSLP.com Website is authored by Martin C Brown这句话改写为清单4所示的RDF XML。
清单4. RDF XML格式的陈述
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-Syntax-ns#" xmlns:si="http://www.recshop.fake/siteinfo#"> <rdf:Description rdf:about="http://www.mcslp.com/ "> <si:author>Martin C Brown</si:author> </rdf:Description> </rdf:RDF> |
采用RDF标准的另一个例子是新闻站点和博客早期提供的连锁系统,它们使用RDF规范定义提要内容和不同的新闻。清单5提供了一个例子。
<?xml version="1.0"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-Syntax-ns#" xmlns="http://my.netscape.com/rdf/simple/0.9/">
<channel> <title>MCslp</title> <link>http://www.mcslp.com</link> <description>MCslp Projects</description> </channel>
<item> <title>Voice enabling XMLtitle> <link>http://mcslp.com/?p=295link> </item>
...
</rdf:RDF> |
RDF标准最初设计的目的是描述Web上的资源、内容和关系。但是RDF现在变成了用于描述一般信息、资源和关系的标准。
语义Web和网格技术都需要定义资源及其之间的关系,使应用程序能够使用不同的信息,并且可以把数据捆绑在一起。
记录联系方式对所有商务应用程序都非常重要,通过有效的XML结构来捕获这些信息可以简化此类数据的处理。
联系信息变化可能很大,因此应该选择XML。比如,有些公司和个人可能有多个地址、电话号码和电子邮件帐户。在XML结构中很容易声明多个此类信息片段。
vCard结构经常在Internet上用于表示联系信息,它独立于平台,很容易生成和导入不同的应用程序。它支持XML结构的某些灵活性,但实际上是一种基于文本的简单格式,使用声明性字段和扩展来提供信息。不同于XML,vCard格式是扁平文本,就是说不能直接向各种元素增加信息。电话号码是一个很好的例子,它不一定和某个地址关联,而仅仅作为记录中的另一个电话号码。
W3联盟提出一种vCard格式的XML,它采用RDF XML标准,以便于格式化和交换联系信息。采用RDF框架可以在声明过程中保留一些结构化信息。比如,RDF标准支持使用包、序列和替代来描述数据。包支持多次声明一个对象(比如多种角色),并且可以在序列不重要时使用包。序列用于定义对象的次序,比如机构中人员角色的层次结构。替代允许从列表中选择一项,比如多个电子邮件地址。
清单6显示了虚拟人物Charles Perston的vCard。
清单6. Charles Perston的vCard
BEGIN:VCARD VERSION:3.0 N:Perston;Charles;;; FN:Charles Perston ORG:Perston Technology; EMAIL;type=INTERNET;type=WORK;type=pref:null@perston.co.uk TEL;type=WORK;type=pref:01234 567890 item1.ADR;type=WORK;type=pref:;;Perston House;Perston;Perstonshire;P1 0NS;UK item1.X-ABADR:gb X-ABUID:5AE47BB6-4E0F-4558-980C-BD3066FA6154/:ABPerson END:VCARD |
采用vCard XML标准,可用清单7中的结构表示同样的信息。
清单7.使用vCard XML标准表示Charles Perston
<vCard:vCard xmlns:rdf="http://www.w3.org/1999/02/22-rdf-Syntax-ns#" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:foaf="http://xmlns.com/foaf/0.1/" vCard:version="3.0" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" vCard:class="PUBLIC" xmlns:vCard="x-urn:cpan:ascope:xml-generator-vcard#"> <vCard:fn>Charles Perston</vCard:fn> <vCard:n> <vCard:family>Perston</vCard:family> <vCard:given>Charles</vCard:given> </vCard:n> <vCard:adr vCard:del.type="pref;work"> <vCard:street>Perston House</vCard:street> <vCard:locality>Perston</vCard:locality> <vCard:region>Perstonshire</vCard:region> <vCard:pcode>P1 0NS</vCard:pcode> <vCard:country>UK</vCard:country> </vCard:adr> <vCard:email vCard:email.type="internet;pref;work">null@perston.co.uk </vCard:email> <vCard:org> <vCard:orgnam>Perston Technology</vCard:orgnam> </vCard:org> </vCard:vCard> |
XML格式更长,但容易理解所看的内容以及各部分之间的关系。这种格式可以了解更详细的信息和细节。比方说,很容易在地址中找到需要的国家,在标准vCard输出中该信息是比较隐含的。
再比如,很容易使用XPath或者SAX事件提取国家的列表,以便了解位于不同地区的联系人的数目。DocBook XML
能够编写文档,然后以多种不同的输出格式创建它,这曾是许多开发团队多年来的梦想。通过DocBook XML就可以实现,它不仅保持了语义标记,也保持了对资料格式化与输出的控制。
控制语义可以指定组成文档的章节和段落。在段落中可进一步详细规定包含的项。比方说可以将命令和函数名放在单独的标签中,如清单8所示。
<para>The <command>compile</command> takes the source code of the material and builds a new class based on the filename. For example,if the filename is <filename>HelloWorld</filename> then the name of the class generated will be <classname>HelloWorld</classname>. |
显示不同的元素时可以选择不同的输出样式和格式,也可选择相同的样式。更重要的是,因为语义信息回会被返回(比如文档可能包含对类名的引用),所以可以在编写索引时用它生成一个列表(该列表包含文档中详细描述的所有类名)。
除了语义标记外,文档的章节和不同部分还可以用特殊的ID标记,用这些ID建立文档不同部分的链接。有些类型可自动完成(章节、部分以及其他生成目录的类型),其他则需要明确建立到其他部分的链接。
转化成目标格式的时这些链接可以自动转换成适当的格式。比如,这个链接会转换为适当的HTML页面或页面中锚的链接。如果要生成PDF,则可以包含目标章节的页码。
这种转换由XSLT样式表完成。现有的标准DocBook XSLT样式表支持到标准HTML、XHTML、PDF(通过FO标准)、Texinfo、Java™ Help和Man页面的转换。使用标准样式表还可以将数据转化成各种不同的大小和风格,书籍、A4页面和幻灯片。
各种输出格式和标记的灵活性意味着:当创建文档时,可以使用相同的文档源代码提供打印的手册、内嵌式的帮助、man页面、在线和上下文感知的信息。使用更传统的模型,可以分别编写这些元素。
DocBook XML在技术文章社区得到了广泛的认可,很多公司所有的文档全部采用DocBook XML标准(或它的一个子集)。
FIX是众多企业间数据交换格式之一,用于在商业活动中交换信息。此类交换信息通常很重要,比如交易支付数据、股票价格和商业信息的交换。
这些需要传输的信息有时候是非常小的包,有时候又是大段的数据。此类信息交换的传统格式是键/值对,这种形式的信息交换效率非常低。使用XML可以简化传递的数据结构,尤其是复杂的数据。
在基于XML的优化版本中,开发人员设法压缩了数据文件的大小,同时使数据更易于阅读。股票数据被压缩到了旧格式的四分之一大小。
除了典型的商业应用外,FIXML不适合用于其他领域。但如果使用FIXML可以提高商业效率,结果是每个人都会受益。
可缩放向量图形(SVG)是一种描述绘图的XML标准。使用SVG可以描述线条、形状、位置及其之间的关系。最有吸引力的是这些信息可以输出为需要的格式,包括可缩放的图形和固定的图片。
SVG解决了传统绘图过程中的一些重要问题。一般是使用专门的绘图程序完成的。在不同程序之间共享信息和绘图一般来说非常困难。保存为SVG意味着任何支持SVG的应用程序都能读取和处理这些文件。
绘图的另一个问题是,将它输出为最常用的(尤其是Web上)格式时,必须在显示或者结合到其他文档前翻译为位图格式(比如JPEG或PNG)。这种传统的方法存在一些问题。首先,原始绘图必须明确(通常是手工)导出为位图格式。
其次,由于位图格式以原始绘图的逐像素表示为基础,为保证图像的质量必须小心选择和输出目标匹配的尺寸和分辨率。比如,屏幕显示的分辨率需要72dpi(或96dpi)以便和多数监视器的标准分辨率匹配。打印输出则需要300到2400 DPI。因此和原始文件相比生成的图像文件可能非常大。
虽然在PostScript和Encapsulated PostScript之前已经存在基于向量的格式,但是对cpu的要求非常高,不适合屏幕显示。
和其他任何向量图像格式一样,SVG也采用各种形状的列表来描述图像内容,而不是生成像素表示。比如矩形只需要给出左上角作为起点,再加上两条边的长度就行了。图像的描述用XML表示。标签包括直线、矩形、多边形、圆等等,可以控制这些元素的样式和格式。
清单9给出了一个例子。这里绘制了一个矩形、一个透明的圆和一个三角形。
清单9.简单的图形
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<polygon points="200,100 300,200 150,250" style="fill:#cccccc; stroke:#000000;stroke-width:1"/>
<rect x="20" y="20" width="250" height="250" style="fill:blue;stroke:black;stroke-width:1; fill-opacity:0.1;stroke-opacity:0.9"/>
<circle cx="100" cy="50" r="40" stroke="red" fill="red" style="fill-opacity:0.5"/>
</svg> |
图1.图像的位图版本
SVG格式描述图像的文件只有500多字节,PNG接近9 KB。
SVG使绘图变得更小、更容易使用以及更容易兼容不同的应用程序。
Dublin Core标准是一种信息分类方法,常用于图书馆。Dublin Core标准有一个XML Schema定义了如何使用XML描述这类信息。Dublin Core可以有效地对各种信息编目,并且使它们易于修改、查询和使用。
Dublin Core目前在信息描述和定义中的应用使语义Web得以现实。通过使用一种统一的标准来描述数据,同时,更重要的是使用精心设计并经过实践检验的解决方案,可以详细描述其他XML文档中的数据,从而可以在不同来源之间有效地交换和比较信息。
Dublin Core规范有自己的模式,但其目的是嵌入更大的XML文档,使用XML名称空间定义描述文档中其他数据所需要的DC元素。作为一个例子,阅读清单10看看如何在RDF XML模式中使用DC分类系统描述RDF实体的内容,比如网站。为此,可以扩展前面的RDF模式示例中的结构。
清单10.在RDF XML模式中使用DC分类系统描述RDF实体的内容
<?xml version="1.0"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-Syntax-ns#" xmlns="http://my.netscape.com/rdf/simple/0.9/" xmlns:dc="http://purl.org/dc/elements/1.1/"> <RSS:channel rdf:about="http://www.xml.com/xml/news.RSS"> <RSS:link>http://mcslp.com/RSS </RSS:link> <dc:description> MCSLP features information,projects and articles from members of the MCSLP team. </dc:description> <dc:subject>MCSLP,Grids,XML,Databases,Programming </dc:subject> <dc:identifier>http://www.mcslp.com</dc:identifier> <dc:publisher>MCSLP</dc:publisher> <dc:rights>Copyright 2008,MCSLP</dc:rights>
</rdf:RDF> |
清单10中使用DC元素添加描述、主题、发布者、版权和标识符信息以便对RSS提要分类。
完整的Dublin Core Metadata Elements Set包括15个元数据元素。
- Title
- Creator
- Subject
- Description
- Publisher
- Contributor
- Date
- Type
- Format
- Identifier
- Source
- Language
- Relation
- Coverage
- Rights
这为描述信息提供了一个广阔的范围。
XForms XML标准用于定义表单中的不同成分(字段、单选按钮和列表等输入控件)以及希望在表单中提供的信息验证。
XForms XML标准和Web开发人员熟悉的HTML、XHTML表单标记非常相似,并将成为XHTML 2.0标准的一部分。
XForms XML基于简单的模型、视图、控制器格式。模型是表单的整体描述,包括字段、输入约束以及数据提交方式。视图定义了出现在表单中的控件、分组及其引用的模型字段。表单控件的格式和呈现由CSS控制。
XForms标准通过更详细地划分表单信息扩展了传统的HTML表单定义。填充表单的过程中可使用动态元素(目前一般只能通过JavaScript或Ajax元素实现)。
清单11中可以看到一个简单的文本输入框和弹出式的选择框。
清单11.简单的文本输入框和弹出选择框
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xforms="http://www.w3.org/2002/xforms"> <head> <title>XForms Sample</title> <xforms:model> <xforms:instance> <Name xmlns=""> <FName /> <LName /> <Title /> </Name> </xforms:instance> </xforms:model> </head> <body> <xforms:select1 ref="Title"> <xforms:label>Title:</xforms:label> <xforms:item> <xforms:label>Mr</xforms:label> <xforms:value>Mr</xforms:value> </xforms:item> <xforms:item> <xforms:label>Mrs</xforms:label> <xforms:value>Mrs</xforms:value> </xforms:item> </xforms:select1> <xforms:input ref="FName"> <xforms:label>First name: </xforms:label> </xforms:input> <xforms:input ref="LName"> <xforms:label>Last name: </xforms:label> </xforms:input> <hr /> <xforms:output value="concat('Hello ',Title,' ',FName,LName)"> <xforms:label>Output: </xforms:label> </xforms:output> </body> </html> |
可以通过Firefox XForms扩展来查看该XForms表单。结果如图2所示。
图2.使用Firefox XForms扩展查看XForms表单
客户发票
很多商业活动中的一个老问题是从纸质的客户发票系统迁移到计算机处理。创建发票结构需要认真考虑各种不同的类型和重复元素。
过去,发票这类商业信息的交换必须建立非常庞大的结构和定义,国际发票信息交换标准包括数百个字段。如果没有交换数据的有效方法,共享发票、订单和其他数据会非常困难。
由于没有统一的标准,很多组织开发出了核心发票标准的各种版本。其中,OASIS组开发的标准可能是最知名的,也是大量公司和组织认可的一种。
这种结构是OASIS开发的更庞大的框架Universal Business Logic(UBL)的一部分,包括多种模式和工作流,从订单、打印发票到支付。这个系统非常复杂,不可能在本文中讨论,不过如果需要一种灵活、互操作的系统,UBL是不错的起点。
本文考察多种不同的XML模式,从简单的描述框架(RDF)到图形格式(SVG)再到商业工作流的完整结构(UBL)。无论哪一种,XML结构和内容的灵活性都大大简化了这些系统的开发。此外,如果需要在不同的平台和环境之间共享数据,XML的跨平台兼容性使得它成为一种理想的选择。对WSDL和SOAP而言,这是最重要的特性之一。