级别: 中级 Nicholas Chase (nicholas@nicholaschase.com), 总裁, Chase & Chase, Inc.
2004 年 7 月 01 日 XForms 的强大之处在于 XForms 客户机可以使用 XML 发送它的数据,然后接收返回的 XML。这种能力可能在 Web 服务领域中特别有用,因为在那里发送和接收的就是 XML:XML 消息。这篇技巧中我将说明如何使用 XForms 浏览器作为 Web 服务客户,发送 SOAP 请求,然后直接在浏览器中显示结果。
本篇技巧假设您对 XForms 和 Web 服务有基本的了解,使用了 Internet Explorer 的 FormsPlayer 插件(请参阅
参考资料以便下载它)。
Web 服务
这篇技巧中,我将说明如何创建向 Web 服务发送请求然后显示结果的 XForms。为了简单起见,我将使用普遍存在的天气的例子,发送一个 ZIP 代码并接收当前的气温。实际的 Web 服务由 Xmethods.net 提供(请参阅
参考资料)。
初始请求只是一个 SOAP 消息,比如:
清单 1. 初始 SOAP 请求
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTemp xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<zipcode xsi:type="xsd:string">02134</zipcode>
</ns1:getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
|
您将使用 XForms 表单为
zipcode 元素提供数据。提交给 Web 服务后将得到如下所示的响应:
清单 2. 响应
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTempResponse xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<return xsi:type="xsd:int">86</return>
</ns1:getTempResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
|
还要使用该表单接收返回值并显示。
基本的 XForms 表单
首先来创建一个基本的表单。XForms 表单由模型和控件组成。模型包括
instance 和
submission 这样的信息,前者表示要显示和提交的数据,后者包括向何处发送以及如何发送数据的信息:
清单 3. 基本的 XForms 表单
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:ns1="urn:xmethods-Temperature"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
>
<head>
<title>XForms and Web Services</title>
</head>
<body>
<object id="FormsPlayer"
classid="CLSID:4D0ABA11-C5F0-4478-991A-375C4B648F58">
<b>FormsPlayer has not loaded. Please check your installation.</b>
</object>
<?import namespace="xforms" implementation="#FormsPlayer" ?>
<xforms:model id="WeatherService">
<xforms:instance id="messages">
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTemp xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/">
<zipcode xsi:type="xsd:string">02134</zipcode>
</ns1:getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
</xforms:instance>
<xforms:submission id="getweather"
method="text-xml-post"
replace="instance"
action="http://services.xmethods.net:80/soap/servlet/rpcrouter"
/>
</xforms:model>
</body>
</html>
|
首先告诉 Internet Explorer 加载
FormsPlayer 对象。如果没有载入,浏览器就显示标签中的内容,告诉用户下载并安装该插件。
接下来是
model ,其中包括
instance 和
submission 。
instance 不仅仅是要显示的数据,同时也是最终将提交的数据,因此就相当于前面
清单 1 中所示的 SOAP 请求。
在真正提交数据的时候,您将更详细地看到 submission 本身。
同时还需要实际创建该表单:
清单 4. 创建表单
...
<xforms:model id="WeatherService">
<xforms:instance id="messages">
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTemp xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/">
<zipcode xsi:type="xsd:string">02134</zipcode>
</ns1:getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
</xforms:instance>
<xforms:submission id="getweather"
method="text-xml-post"
replace="instance"
action="http://services.xmethods.net:80/soap/servlet/rpcrouter"
/>
</xforms:model>
<xforms:input ref="instance('messages').//zipcode">
<xforms:label>Zip code: </xforms:label>
<xforms:hint>Enter a zip code and submit the form for the current
temperature in that area.</xforms:hint>
</xforms:input>
</body>
</html>
|
图 1: 简单文本控件
如果用户改变控件中的值,它就修改包含在实例中的 XML 的相应节点。比方说如果把字段中的值改为
10314 ,那么实例文档在内存中看起来就是这样:
清单 5. 实例文档
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTemp xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<zipcode xsi:type="xsd:string"
>10314</zipcode>
</ns1:getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
|
将提交给服务的就是这个文档。但是在进行这一步之前要看一看表单的状态。
改变状态
在提交表单时,实际上是用具有不同结构的另一个实例文档代替了这个实例文档,因此要显示器中的信息,您就需要适合那种结构的控件而不是原来的控件。但是不能同时在页面中包括这些控件,因为必有一个引用不存在的节点从而造成错误。为了避免这个问题,您需要建立一个条件,根据这个条件每次只显示一组控件。可以使用
switch 来完成:
清单 6. 增加开关
...
</xforms:model>
<xforms:switch id="switch1">
<xforms:case id="requestGUI">
<xforms:input ref=".//zipcode">
<xforms:label>Zip code: </xforms:label>
<xforms:hint>Enter a zip code and submit the form for the current
temperature in that area.</xforms:hint>
</xforms:input>
<xforms:trigger style="display:block">
<xforms:label>Change to results case</xforms:label>
<xforms:action ev:event="DOMActivate">
<xforms:toggle case="responseGUI" />
</xforms:action>
</xforms:trigger>
</xforms:case>
<xforms:case id="responseGUI">
Results go here.
<xforms:trigger>
<xforms:label>Change to request case</xforms:label>
<xforms:action ev:event="DOMActivate">
<xforms:toggle case="requestGUI" />
</xforms:action>
</xforms:trigger>
</xforms:case>
</xforms:switch>
</body>
</html>
|
这里分为两种情况。第一种是默认显示的表单,这里增加了一个
trigger 或者按钮,单击时将会激活,如图 2 所示。
图 2. 增加触发器
激活的时候将执行
action 元素中的所有内容,就本例而言就是切换到
responseGUI 状态。这样就告诉浏览器只显示第二种情况,如图 3 所示:
图 3. 显示结果
使用这个表单用户可以单击按钮来回切换。现在需要增加表单提交的功能。
提交表单
当然这样的表单还不够完善。最终的目标是希望在提交表单值后切换到结果显示。为此可以在动作中增加提交的功能:
清单 7. 在动作中增加提交
...
<xforms:trigger style="display:block">
<xforms:label>Get current temperature</xforms:label>
<xforms:action ev:event="DOMActivate">
<xforms:send submission="getweather" />
<xforms:toggle case="responseGUI" />
</xforms:action>
</xforms:trigger>
...
|
这里仅仅告诉浏览器当用户单击该按钮时执行提交
getweather 。创建该提交时还需要增加一些信息:
清单 8. 指定提交为 XML post
...
<xforms:submission id="getweather"
method="text-xml-post"
replace="instance"
action="http://services.xmethods.net:80/soap/servlet/rpcrouter"
/>
...
|
该提交规定将其作为 XML post 提交,这正是 SOAP 消息使用的方式,而且您希望替换该实例。这样在返回的时候,该实例看起来类似于清单 9:
清单 9. 返回的实例
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTempResponse xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<return xsi:type="xsd:int"
>86</return>
</ns1:getTempResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
|
为了看到返回的结果,您需要从
resultGUI 部分进行检索:
清单 10. 检索结果
<xforms:case id="responseGUI">
<xforms:output ref="instance('messages')//return"
style="width:40ex;display:block;">
<xforms:label>Current Temperature:</xforms:label>
</xforms:output>
</xforms:case>
...
|
这样当提交该表单时就得到了返回的气温值,如图 4 所示。
图 4. 结果页面
结束语
因为 XForms 表单发送和接收 XML 文档,因此很适合作为 Web 服务客户程序。这篇技巧中,我说明了使用 XForms 表单从 Web 服务请求信息的基本过程。这个过程如下:
- 浏览器显示实例文档中的信息,该文档采用 SOAP 请求的结构。
- 浏览器向 Web 服务发送该实例文档(包含 ZIP 代码)。
- Web 服务向浏览器发送响应(包含气温),后者用响应代替原来的实例文档。
- 浏览器切换到第二组控件,显示 Web 服务返回的信息。
参考资料
关于作者  | |  | Nicholas Chase 参与了 Lucent Technologies、Sun Microsystems、Oracle 和 Tampa Bay Buccaneers 等公司的网站开发。Nick 曾是一名高中物理教师、放射性废物设备初级管理人员、在线科幻小说杂志编辑、多媒体工程师和 Oracle 讲师。最近,他成为 Site Dynamics Interactive Communications(位于佛罗里达州克利尔沃特市)的首席技术官,而且还是三本有关 Web 开发书籍的作者,包括
Java and XML From Scratch(Que)和即将出版的
Primer Plus XML Programming(Sams)。他乐于听取读者的意见,可以通过
nicholas@nicholaschase.com与他联系。
|
对本文的评价
|