Web 服務
為了簡單起見,我再一次使用普遍存在的天氣示例,發送一個 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>
lt;/SOAP-ENV:Body>
</SOAP-ENV:Envelope>
在該例中,不用使用表單直接對這條消息進行操作。您將創建另一個稍微友好一點的實例,然後在提交該實例之前,使用數據填充上述結構。
基本的 XForms 表單
首先來創建一個基本的表單。XForms 表單由一個模型和一些控件組成,因此我們從操作它的基本實例和控件開始,如清單 2 所示。
清單 2. 基本的 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="guiInstance" XMLns="">
<inputData>
<zip>enter zip</zip>
</inputData>
</xforms:instance>
</xforms:model>
<xforms:input ref="instance('guiInstance')//zip">
<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>
該頁面從定義所有相關名稱空間開始,接著轉向導入 FormsPlayer 對象及其名稱空間。然後,您就可以進入表單本身,圖 1 中顯示了該表單。
從模型開始,當您為其做好准備時,該模型最終將既包含實例又包含提交信息。同時,您恰好已經創建了一個非常簡單的實例來保存您正尋找的數據。這很可能就是來自您的遺留系統的一個復雜文檔。在頁面的結尾處,您已經定義了一個限制為 zip 元素的簡單輸入框。
圖 1: 輸入控件
現在,您將准備提交表單。
創建提交框架
注意,我說的是“您將准備提交表單”,而不是“您將提交表單”。正如在第一篇技巧中那樣,您必須處理這樣一種情況,在該情況下,您需要為已經不存在的關聯數據(Web 服務結果)創建控件(結果輸出)。為了小心起見,可以創建一個通過一對 case 和一個 toggle 控制的開關,如清單 3 所示:
清單 3. 添加開關
...
</xforms:instance>
</xforms:model>
<xforms:switch>
<xforms:case id="request">
<h2>Enter your zip code</h2>
<xforms:input ref="instance('guiInstance')//zip">
<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:case>
<xforms:case id="response">
<h2>And the result is...</h2>
The zip code you requested is:
<xforms:output ref="instance('guiInstance')//zip" />
</xforms:case>
</xforms:switch>
</body>
</Html>
每次只能顯示一種情況(case)—— 默認情況下,顯示第一種情況。要轉向另一種情況,需要添加起 trigger 作用的 toggle ,如清單 4 所示:
清單 4. 添加觸發器
...
<xforms:case id="request">
<h2>Enter your zip code</h2>
<xforms:input ref="instance('guiInstance')//zip">
<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>Get current temperature</xforms:label>
<xforms:action ev:event="DOMactivate">
<xforms:toggle case="response" />
</xforms:action>
</xforms:trigger>
</xforms:case>
正如您在圖 2 中可以看到的,觸發器被表示為一個簡單的按鈕。
圖 2: 觸發器按鈕
當用戶單擊該按鈕,或者以其他方式激活觸發器時,您可以獲得第二種情況,一會兒我將展示給您。
首先來看一看第二個實例。
添加第二個實例
現在,即將添加第二個實例到頁面。因為 Web 服務正在查找 XML,所以該實例就是 Web 服務正在查找的消息,如清單 5 所示:
清單 5. 添加第二個實例
...
<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">NO DATA SUBMITTED</zipcode>
</ns1:getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
</xforms:instance>
<xforms:instance id="guiInstance" XMLns="">
<inputData>
<zip>enter zip</zip>
</inputData>
</xforms:instance>
</xforms:model>
...
這個難題的一個重要部分就是 zipcode 元素,通過將另一個 output 控件添加到 response 情況,您可以看見該元素的狀態,如清單 6 所示:
清單 6. 查看提交的數據
...
<xforms:case id="response">
<h2>And the result is...</h2>
The zip code you requested is:
<xforms:output ref="instance('guiInstance')//zip" />
<br />
The zip code you are going to send is:
<xforms:output ref="instance('messages')//zipcode" />
</xforms:case>
...
如果輸入一個郵政編碼並單擊觸發器按鈕,您可以看見事物的當前狀態,如圖 3 所示。
圖 3. 監視提交的數據
顯然,這無法奏效。您需要將請求的數據放入想要提交的實例中。
將值移入提交實例
簡而言之,當用戶激活觸發器時,您應該將數據從 guiInstance zip 元素復制到 messages zipcode 元素中。在進行復制時,值可以直接轉換到表單中:
清單 7: 將值復制到消息實例中
...
<xforms:trigger style="display:block">
<xforms:label>Get current temperature</xforms:label>
<xforms:action ev:event="DOMactivate">
<xforms:setvalue ref="instance('messages')//zipcode"
value="instance('guiInstance')//zip" />
<xforms:toggle case="response" />
</xforms:action>
</xforms:trigger>
...
當用戶激活觸發器時,該表單會將 messages 實例中 zipcode 元素的值設置為 guiInstance 實例中 zip 元素的值。要查看這一點,需要重載該表單並提交它(參見圖 4)。
圖 4. 設置 zipcode 元素的值
現在,您必須處理提交問題。
提交實例
要提交 message 實例,需要創建作為模型一部分的 submission 元素,並從觸發器發送它,如清單 8 所示:
清單 8. 創建 submission 元素
...
<xforms:instance id="guiInstance" XMLns="">
<inputData>
<zip>enter zip</zip>
</inputData>
</xforms:instance>
<xforms:submission id="getweather"
method="text-XML-post"
replace="instance"
ref="instance('messages')"
action="http://services.xmethods.Net:80/soap/servlet/rpcrouter"
/>
</xforms:model>
<xforms:switch>
<xforms:case id="request">
...
<xforms:trigger style="display:block">
<xforms:label>Get current temperature</xforms:label>
<xforms:action ev:event="DOMactivate">
<xforms:setvalue value="instance('guiInstance')//zip"
ref="instance('messages')//zipcode"/>
<xforms:toggle case="response" />
<xforms:send submission="getweather"/>
</xforms:action>
</xforms:trigger>
</xforms:case>
<xforms:case id="response">
<h2>And the result is...</h2>
The temperature in zip code
<xforms:output ref="instance('guiInstance')//zip" />
is approximately
<xforms:output ref="instance('messages')//return" /> degrees.
</xforms:case>
</xforms:switch>
</body>
</Html>
這樣就創建了 submission 元素,從觸發器發它,並提取返回的值以便顯示。正如您在圖 5 中可以看到的,您可以訪問原始數據——因為它們仍然存在於原始實例中,而且您還能夠將一個單獨的實例提交給服務。
圖 5. 最終結果
結束語
XForms 像 Web 服務客戶機一樣便利,因為它們能夠發送和接收 XML,但將 Web 服務請求用作數據實例可能有些麻煩和不便。本篇技巧已經解釋了如何創建一個實例用於操作數據,同時創建另一個實例用於發送和接收數據。您將了解:
創建基本的表單。
創建兩個實例。
在提交實例之前,將數據從以前的實例遷移到另一個實例中。
提交請求。
接收響應。