跳到内容

XRX/服务器字段验证

来自维基教科书,开放的书籍,开放的世界
< XRX

您在表单字段中拥有要验证的数据。例如,您要验证邮政编码是否有效。您希望在服务器上执行验证,因为将完整数据集加载到 Web 浏览器中进行验证会减慢表单加载速度。

向远程服务器发送数据并将结果返回,而不会重新加载整个表单,是 XForms 的核心功能。XRX 的优势在于,可以在不编写任何 JavaScript 代码的情况下实现这一功能。我们将使用几个组件演示此技术。

  1. 我们将创建一个服务器端 RESTful 组件,如果字段通过了服务器端检查,则返回一个简单的“OK”消息,如果失败,则返回一个错误消息。
  2. 我们将向该字段添加一个操作,以检测该字段中的值是否更改。这可以针对用户键入的每个字符执行,或者当用户从该字段中跳出时执行。
  3. 此操作将触发对服务器的提交并返回结果到模型中。RESTful 服务的输入参数和服务结果将存储在模型中的单独实例中。

示例代码

[编辑 | 编辑源代码]

在此示例中,我们将检查输入的数据是否为有效的邮政编码(美国邮政编码)。

这是来自表单的示例代码

输入字段

[编辑 | 编辑源代码]

在以下代码中,我们将 XForms 操作添加到输入中。我们触发的事件是 **DOMFocusOut**,它在用户从字段中跳出时触发。我们执行两个操作。

  1. 我们使用 xf:setvalue 函数将值放入传出实例中。
  2. 我们触发 RESTful Web 服务。

输入字段和操作的示例代码片段

[编辑 | 编辑源代码]
<xf:input ref="zip-code" incremental="true">
    <xf:label>Zip Code:</xf:label>
    <xf:hint>Five digit zip code</xf:hint>
    <xf:action ev:event="DOMFocusOut">
        <!-- copy the value in the form to the outgoing submission instance -->
        <xf:setvalue ref="instance('zip-check')/zip-code" value="instance('save-data')/zip-code"/>
        <xf:send submission="zip-check-submission"/>
    </xf:action>
</xf:input>

提交元素

[编辑 | 编辑源代码]

这是添加到 XForms 模型中的附加提交元素。方法为 HTTP GET,它将我们传出“zip-check”实例中的所有参数添加到 URL 的末尾。操作是 XQuery 脚本的名称。在本例中,我使用了一个相对路径,这在 XQuery 检查与生成 XForms 应用程序的 XQuery 脚本位于同一集合中时很常见。

<xf:submission id="zip-check-submission" method="get" action="zip-check.xq" 
       ref="instance('zip-check-submission')" 
       replace="instance" instance="zip-check-results" 
       separator=";"/>

传出值和传入结果的实例

[编辑 | 编辑源代码]
 <!-- store the outgoing query parameters for the zip check. -->
    <xf:instance id="zip-check">
        <data xmlns="">
            <zip-code/>
        </data>
    </xf:instance>
    
    <!-- a place to store the results of a check -->
    <xf:instance id="zip-check-results">
        <data xmlns=""/>
    </xf:instance>

这将导致查询的结果成为 URL 参数。

zip-check.xq?zip-code=55426

服务器端 XQuery 示例

[编辑 | 编辑源代码]

服务器端 XQuery 示例

[编辑 | 编辑源代码]
xquery version "1.0";

let $file-path := '/db/org/syntactica/wiki-books/xrx/field-server-check/zip-codes.xml'
let $zip-codes := doc($file-path)/code-table/items/item/value

let $zip-code := request:get-parameter('zip-code', '')

return
<results>{
   if (some $item in $zip-codes satisfies ($zip-code = $item))
     then
        <message class="ok">OK</message>
     else
        <message class="error">{concat('zip-code: ', $zip-code, ' is not valid.')}</message>
}</results>

正确值的示例响应

[编辑 | 编辑源代码]
<results>
   <message class="ok">OK</message>
</results>
<results>
   <message class="error">zip-code: 55999 is not valid.</message>
</results>

示例数据文件

[编辑 | 编辑源代码]
<code-table>
    <name>zip-code</name>
    <items>
        <item>
            <label>St. Louis Park, MN</label>
            <value>55426</value>
        </item>
        <item>
            <label>Mendota Heights, MN</label>
            <value>55118</value>
        </item>
        <item>
            <label>Minneapolis, MN</label>
            <value>55401</value>
        </item>
        <item>
            <label>Edina, MN</label>
            <value>55439</value>
        </item>
    </items>
</code-table>

完整的 XForms 示例

[编辑 | 编辑源代码]
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xf="http://www.w3.org/2002/xforms">
    <head>
        <title>Form Title</title>
        <style type="text/css"><![CDATA[
            
            @namespace xf url("http://www.w3.org/2002/xforms");
            body {
                font-family:Helvetica, sans-serif;
            }
            ]]>
            </style>
        <xf:model>

            <xf:instance id="save-data">
                <data xmlns="">
                    <zip-code>44526</zip-code>
                </data>
            </xf:instance>
            
            <xf:instance id="zip-check">
                <data xmlns="">
                    <zip-code>44526</zip-code>
                </data>
            </xf:instance>
            
            <!-- place to store the results of a the zip code -->
            <xf:instance id="zip-check-results">
                <data xmlns="">
                    <id/>
                </data>
            </xf:instance>

            
            
            <xf:submission id="zip-check-submission" method="get" action="zip-check.xq"
                ref="instance('zip-check')" replace="instance" instance="zip-check-results"
                separator=";"/>
            
        </xf:model>
    </head>
    <body>

        <xf:input ref="instance('save-data')/zip-code" incremental="true">
            <xf:label>Zip Code:</xf:label>
            <xf:hint>Five digit zip code.</xf:hint>
            <xf:action ev:event="DOMFocusOut">
                <!-- copy the value in the form to the outgoing submission instance -->
                <xf:setvalue ref="instance('zip-check')/zip-code"
                    value="instance('save-data')/zip-code"/>
                <xf:send submission="zip-check-submission"/>
            </xf:action>
        </xf:input>

        <xf:output ref="instance('zip-check-results')/message">
            <xf:label>Response:</xf:label>
        </xf:output>

        <xf:trigger submission="zip-check-submission">
            <xf:label>Check Zip Code</xf:label>
        </xf:trigger>
    </body>
</html>

即使数据集很小或验证检查很简单,也可以使用此技术。表单设计者必须考虑在表单中存储验证规则与来回访问服务的开销之间的权衡。此模式有几种变体。一种变体是使用“建议”模式,在用户输入数据时建议多个值中的一个。在这种情况下,每个更改的字符都可能触发新的可能值列表。

华夏公益教科书