XForms 是下一代的基于 Web 的数据处理技术。它用 XML 数据模型和表示元素代替了传统的 HTML 表单。本系列文章有三个部分,介绍了 XForms 及其功能,内容包括基本的 XForms 模型和表单、各种不同类型的控件、基本和高级表单提交技术。本文是此系列文章的第二部分,重点讨论如何使用各种控件创建基于 XForms 的表单以及如何创建数据模型。
简介
XForms 的发展势头迅猛,常见浏览器使用扩展或插件来支持它,此外还有 IBM® Workplace Forms 之类的技术(请参见参考资料部分)。它的灵活和强大对 Web 开发人员很有吸引力,内存占用少和客户端处理又让系统管理员十分感兴趣。W3C 正在审查 XForms 1.1 工作草案文档(1.0 是正式的 Internet 推荐标准,和 XHTML、PNG 以及 CSS 具有同等的地位),IBM 目前带头致力于把那些竞争的基于 XML 的表单标准与 XForms 的特性和功能结合起来。
本文说明了如何使用各种控件创建基于 XForms 的表单、如何建立数据模型以及不同类型的基本提交动作。第 1 部分讨论了各种浏览器以及为了查看和与 XForms 文档交互所需要的插件,本文不再赘述。如果阅读过上一部分,或者已经为使用的浏览器安装了插件,可以直接下载本文中的代码查看示例 XForms。
回页首
创建基本的表单
本系列的第 1 部分中已经创建了一个非常简单的表单,其中包括一个文本输入字段和一个提交按钮,可以向本地主机上假想的搜索引擎发送请求(如图 1 所示)。这类表单仍然很常见,尽管它通常不是孤立在单独的网页上。
图 1. 非常简单的 Web 表单
非常简单的 Web 表单
这是个很好的起点,我们再来看看 XHTML 和 XForms 代码(清单 1)。XForms 的专用代码用粗体字显示,很容易看到,文档的其他部分是纯粹的 XHTML 1.1 Strict。
清单 1. 起点
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ev="http://www.w3.org/2001/xml-events">
<head>
<title>Search Form</title>
<xf:model>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
</head>
<body>
<h1>Search Form</h1>
<p>
Enter a search string, then click the Search button.
</p>
<p>
<xf:input ref="query"><xf:label>Find:</xf:label></xf:input>
<xf:submit
submission="submit-search"><xf:label>Search</xf:label>
</xf:submit>
</p>
</body>
</html>
增加 XForms 名称空间(使用 xf: 前缀)后,已经有了一个 <xf:model> 块,它声明了名为 submit-search 的提交动作,可以使用标准的 HTTP GET 方法提交指定的搜索字符串。<body>, <xf:input> 和 <xf:submit> 元素中的内容构成了简单的表单,包括输入字段和提交按钮,后者触发 <xf:model> 中声明的动作。
如果愿意的话,可以直接试一试,<xf:input> 和 <xf:submit> 元素的距离、先后或位置没有任何特殊要求,它们可以出现在文档 <body> 的任何地方。表单的输入部件表示与其数据模型分离开来。
由于将使用该文档作为本文中其他 XForms 文档的出发点,这里还提供了 XMLSchema 和 xml-events 的 XML 名称空间声明,XForms 利用这两个辅助标准分别提供标准数据类型和表单事件。
回页首
创建一个简单的模型
XForms 的吸引人的原因之一是其将数据模型从表示中分离出来的方法。再看看清单 1,模型(<xf:model> 块中)本身存在于 XHTML 文档的 <head> 中。
当然,除了一个提交动作之外这个模型完全是空的。它不含任何数据!
不过,先别忙。系统(在这里就是支持 XForms 的浏览器)为您创建了一个(如清单 2 所示),其中包含表单引用的数据字段。
清单 2. 简单表单默认的完整 <xf:model>
<xf:model>
<xf:instance>
<data xmlns="">
<query/>
</data>
</xf:instance>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
显式地包含这种形式的实例为表单额外增加了一层验证;表单控件(比如这个简单表单中的文本字段和提交按钮)所引用的字段必须存在于模型实例之中。引用不存在的实例元素的控件要么不能呈现,要么生成错误消息(取决于 XForms 实现)。
回页首
默认值
如果显式地声明数据实例,可用它来定义默认值,只要将默认值放在字段元素中即可。清单 3 中的模型和清单 2 相同,只不过为查询提供了一个有帮助的默认值(如图 2 所示)。
清单 3. 在 <xf:instance> 中直接包含默认值
<xf:model>
<xf:instance>
<data xmlns="">
<query>One or more search keywords.</query>
</data>
</xf:instance>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
图 2. 在模型实例中包含帮助性的提示或者有意义的默认值
在模型实例中包含帮助性的提示或者有意义的默认值
回页首
隐藏值和隐藏控件
用户触发提交动作时,XForms 发送完整的 XML 文档(数据模型实例)。创建模型实例时可以包含需要的任何数据。
因而不再需要在表单中使用隐藏控件。如果有些数据需要发送到服务器上的表单处理程序,但是又不必显示给用户(或者需要保持不变),那么可以将其添加到模型实例中(如清单 4 所示)。
清单 4. 在实例而不是表单中包含隐藏数据或者常量
<xf:model>
<xf:instance>
<data xmlns="">
<query>One or more search keywords.</query>
<engine-version>2</engine-version>
<results>25</results>
</data>
</xf:instance>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
该例中,<engine-version> 和 <results> 永远不会被表单控件引用,也不会被用户看到(除非用户查看源代码)。这些数据组作为查询的一部分发送给 imaginary-search-engine,imaginary-search-engine 可以利用它们选择搜索引擎和设置返回的结果数。
回页首
加载实例
如果数据模型很大,或者需要向用户隐藏某些数据,可以从外部 XML 文件加载实例(如清单 5 所示)。
清单 5. XML 文件中的简单模型实例
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="">
<query>One or more search keywords.</query>
<engine-version>2</engine-version>
<results>25</results>
</data>
只要让 <xf:instance> 引用具体的实例 URL(如清单 6 所示)就可以了。
清单 6. 引用外部模型实例
<xf:model>
<xf:instance src="search-instance.xml"/>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
由于 <xf:instance> 的 src 属性可以从任何 URL 加载 XML 数据,可以用 XForms 编辑或原样表示任何数据。多数 XForms 实现都要求源文档的 URL 在同一个域中,但部分 XForms 实现也允许您配置一个可信任的站点列表。
回页首
XML 数据中的引用
加载 XML 文件作为数据实例时,有可能无法控制 XML;数据也许是数据库或者其他某个应用程序提供的。如何引用 XML 中的某个元素呢?到目前为止,您还只看到了引用与数据模型匹配的元素。
XForms 表单元素使用的数据模型引用实际上是 XPath 表达式,因此可用 XPath 表达式来引用模型中的任何元素。清单 7 显示了一个扩展后的实例,其中包括一些嵌套元素。
清单 7. 更复杂的数据模型实例
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="">
<query>One or more search keywords.</query>
<engine-version>2</engine-version>
<results>25</results>
<some>
<additional>
<info status="important">Nested info.</info>
</additional>
</some>
</data>
可用 XPath 表达式 some/additional/info(或者 /data/some/additional/info,如果使用绝对路径的话)来访问 <info> 元素,或者用 some/additional/info/@status 访问 <info> 元素的 status 属性。清单 8 显示了可用于编辑该数据文件的表单,在这里假设 Web 服务器支持 PUT 方法(可能需要某种身份验证来保护这种功能)。
清单 8. 编辑更复杂的 XML 数据
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms">
<head>
<title>Search Form</title>
<xf:model>
<xf:instance src="http://localhost/~chrish/data.xml"/>
<xf:submission action="http://localhost/~chrish/data.xml"
method="put" id="submit-edit"/>
</xf:model>
</head>
<body>
<h1>XPath</h1>
<p>
Change the info and status!
</p>
<p>
<xf:input ref="some/additional/info"><xf:label>New
info:</xf:label></xf:input><br/>
<xf:input ref="some/additional/info/@status"><xf:label>New
status:</xf:label></xf:input>
<xf:submit
submission="submit-edit"><xf:label>Save</xf:label></xf:submit>
</p>
</body>
</html>
无论在客户机还是服务器上,对 XForms 来说 XPath 都是一种很好的辅助技术;一旦掌握了 XPath,就可以在表单和表单处理程序中使用它。
回页首
控件的类型
到目前为止,我们只用到了 <xf:input> 和 <xf:submit> 控件,但是 XForms 还提供了很多其他的表单控件。我们来看看这些控件及其在 HTML 中的等价物。
<xf:group>(HTML <fieldset>)用于对表单中的控件进行逻辑分组。清单 9 说明了如何使用 <xf:group> 为三个输入字段加标签。
清单 9. 分组控件
<xf:group>
<xf:label>Personal Information</xf:label>
<p><xf:input ref="lastname"><xf:label>Last
name:</xf:label></xf:input></p>
<p><xf:input ref="firstname"><xf:label>First
name:</xf:label></xf:input></p>
<p><xf:input
ref="address"><xf:label>Address:</xf:label></xf:input></p>
</xf:group>
<xf:input>(HTML <input type="text">)显示一个标准的文本输入字段,我们已经多次用到了它。
<xf:secret>(HTML <input type="password">)显示一个文本输入字段,输入的内容隐藏起来,适用于输入口令或者其他保密数据。<xf:secret> 与文档源代码中的 <xf:input> 完全相同。
<xf:select appearance="full">(HTML <input type="checkbox">)为用户提供一个或多个可选项,允许多选。清单 10 给出了一个例子。
清单 10. 多选控件
<xf:select ref="potato-chips" appearance="full">
<xf:label>Favourite flavours:</xf:label>
<xf:item><xf:label>Dill
Pickle</xf:label><xf:value>dill</xf:value></xf:item>
<xf:item><xf:label>Ketchup</xf:label><xf:value>ketchup<
/xf:value></xf:item>
<xf:item><xf:label>Plain</xf:label><xf:value>plain<
/xf:value></xf:item>
<xf:item><xf:label>Salt &
Vinegar</xf:label><xf:value>snv</xf:value></xf:item>
</xf:select>
<xf:select appearance="minimal">(HTML <select multiple>)用于从菜单或列表中选择一个或多个项,对 appearance 属性使用 minimal 可以在更小的区域中呈现项目列表。
<xf:select1>(HTML <input type="radio">)类似于 <xf:select>,但是只允许用户从列表中选择一项。它可以呈现为一组单选按钮、可滚动的选择区域或者菜单,使用 appearance 属性告诉呈现引擎应该呈现为什么。
<xf:select1> 和嵌套的 <xf:choices>(HTML <select> 和嵌套的 <optgroup>)允许用户从分组列表中选择一项。<xf:choices> 子列表的标签呈现在列表中,但是不能选择。清单 11 显示了一个饮料列表让用户选择,用户也可以从非酒精和酒精饮料中选择。
清单 11. 从多个分组中选择一项
<xf:select1 ref="drink">
<xf:label>Drink:</xf:label>
<xf:item><xf:label>None</xf:label><xf:value>none
</xf:value></xf:item>
<xf:choices>
<xf:label>Soft drinks</xf:label>
<xf:item><xf:label>Juice</xf:label><xf:value>juice
</xf:value></xf:item>
<xf:item><xf:label>Milk</xf:label><xf:value>milk
</xf:value></xf:item>
<xf:item><xf:label>Soda</xf:label><xf:value>soda
</xf:value></xf:item>
<xf:item><xf:label>Water</xf:label><xf:value>water<
/xf:value></xf:item>
</xf:choices>
<xf:choices>
<xf:label>Wine and beer</xf:label>
<xf:item><xf:label>Beer</xf:label><xf:value>beer<
/xf:value></xf:item>
<xf:item><xf:label>Red
wine</xf:label><xf:value>redwine</xf:value></xf:item>
<xf:item><xf:label>White
wine</xf:label><xf:value>whitewine</xf:value></xf:item>
</xf:choices>
</xf:select1>
<xf:textarea>(HTML <textarea>)显示一个多行文本输入字段,如果默认值不合适可使用 CSS 样式控制区域的大小。
<xf:trigger>(HTML <input type="button">)呈现一个动作按钮。按钮没有预定义的行为,因此需要为其附加一个动作,按钮被激活时将触发该动作。清单 12 中的 <xf:trigger> 激活一个 JavaScript™ 函数,名为 calculate()。
清单 12. 调用 JavaScript 函数 calculate() 的按钮
<xf:trigger>
<xf:label>Calculate</xf:label>
<script ev:event="DOMActivate" type="text/javascript">
calculate();
</script>
</xf:trigger>
要注意,这里第一次使用 ev: 名称空间,虽然在前面的基本表单的示例中早已声明。它用于引用标准 XML Events 属性 ev:event,它告诉触发器什么时候激活脚本。
<xf:trigger>(HTML <input type="image">)也可用于为表单添加图像按钮,只需在 <xf:label> 元素中插入 <img> 元素或者使用 CSS 将图像作为元素的背景即可。
如果正在把某些 HTML 表单升级到 XForms 表单,可以使用 <xf:trigger>(HTML <input type="reset">)增加 Reset 按钮(升级规范可能要求“全部功能”,包括无用的 Reset 按钮)。清单 13 说明了如何创建一个表单复位按钮,但是不要在新表单中使用它:最终用户永远不会有意识地单击 Reset 按钮。
清单 13. 实现无用的历史遗留物:Reset 按钮
<xf:trigger>
<xf:label>Reset</xf:label>
<xf:reset ev:event="DOMActivate"/>
</xf:trigger>
<xf:upload>(HTML <intput type="file">)用于实现文件上传。和其他控件相比这个更复杂一点,因为它需要一种特殊的 <xf:submission> 方法:form-data-post(如清单 14 所示)。
清单 14. 使用 <xf:submission> 方法上传文件
<xf:model>
...
<xf:submission action="http://localhost/upload-engine"
method="form-data-post" id="upload"/>
</xf:model>
表单下方的 <xf:upload> 元素看起来类似于 <xf:submit> 或 <xf:input>(如清单 15 所示)。
清单 15. 使用 <xf:upload> 上传文件
<xf:upload ref="upload"><xf:label>Upload a
file:</xf:label></xf:upload>
另外,还有一些 HTML 中不存在的控件。
<xf:output> 允许在文档中增加一些文本值。比如清单 7 中向数据模型增加了 <results> 元素。虽然用户不能修改它,但是可以通过编辑模型来改变它(特别是如果使用外部 XML 文件中定义的模型的话)。可以使用 <xf:output> 元素向用户显示这些信息(如清单 16 所示)。
清单 16. 使用 <xf:output> 显示模型中的数据
<p>
Your search will return a maximum of
<xf:output ref="results"> matches.
</p>
<xf:range> 为用户显示一个范围选择条(slide)或者适合于获得受约束值的其他控件。比方说,可以用三个 range 让用户输入红/绿/蓝中的一个作为突出显示搜索结果的颜色(如清单 17 所示)。
清单 17. 使用范围输入控件
<p>
Keyword highlight:<br/>
<xf:range ref="r" start="0" end="100" step="1"><xf:label>Red</xf:label></xf:range><br/>
<xf:range ref="g" start="0" end="100" step="1"><xf:label>Green</xf:label></xf:range><br/>
<xf:range ref="b" start="0" end="100" step="1"><xf:label>Blue</xf:label></xf:range>
</p>
现在介绍了各种 XForms 输入控件(和一个输出控件),下面来看看各种不同的提交动作。
回页首
基本提交动作
XForms 标准支持通常的 HTML 表单提交方法,但是 HTML 需要 method 和 enctype 来指定提交方法,而 XForms 只需要一个 method。
<xf:submission method="form-data-post" action="url"/> 和 HTML 中的 <form method="post" enctype="multipart/form-data"> 相同,可以按同样的方法在收到 URL 时被处理。
<xf:submission method="get" action="url"/> 和 HTML 中的 <form method="get"> 相同。
<xf:submission method="urlencoded-post" action="url"> 和 HTML 中的 <form method="post" enctype="application/x-www-form-urlencoded"> 相同。
除了和 HTML 兼容的提交方法之外,XForms 还定义了两种新的提交动作,method="post" 和 method="put"。
method="post" 动作将表单数据模型实例作为 XML 文档 post 给接收 URL,适用于 XSLT 或者其他 XML 处理技术。客户机不需要制定编码或者转义,服务器上也不需要特殊处理(除了标准 XML 解析以外)。
method="put" 动作将表单数据模型实例作为 XML 文档 put 给目标 URL。如果服务器支持 PUT 方法,并且允许对目标 URL 使用该方法,该 XML 文档将代替目标 URL 上的文件。可利用该方法现场编辑“任何”XML 文档,只需要通过和后来 put 动作要用到的相同的 URL 加载数据模型实例即可。
纯 XML post 和 put 方法是 XForms 目标的一部分,为数据处理带来了一定程度的灵活性。
回页首
结束语
XForms 提供了一致的、清晰的基于 XML 的数据模型,可以在文档或者页面处理期间加载的外部文件中直接包含任意的 XML。该标准支持现在所有 HTML 表单控件的等价物,并增加了另外两个有用的控件用于范围选择和显示数据。基本 XForms 提交动作包含了原来的 HTML 的提交方法,并增加了两种基于 XML 的方法。本文全面介绍了这些控件,您可以以此为基础开始自己的 XForms 体验。
XForms 学习交流群:38587873/. 欢迎大家入群讨论。
简介
XForms 的发展势头迅猛,常见浏览器使用扩展或插件来支持它,此外还有 IBM® Workplace Forms 之类的技术(请参见参考资料部分)。它的灵活和强大对 Web 开发人员很有吸引力,内存占用少和客户端处理又让系统管理员十分感兴趣。W3C 正在审查 XForms 1.1 工作草案文档(1.0 是正式的 Internet 推荐标准,和 XHTML、PNG 以及 CSS 具有同等的地位),IBM 目前带头致力于把那些竞争的基于 XML 的表单标准与 XForms 的特性和功能结合起来。
本文说明了如何使用各种控件创建基于 XForms 的表单、如何建立数据模型以及不同类型的基本提交动作。第 1 部分讨论了各种浏览器以及为了查看和与 XForms 文档交互所需要的插件,本文不再赘述。如果阅读过上一部分,或者已经为使用的浏览器安装了插件,可以直接下载本文中的代码查看示例 XForms。
回页首
创建基本的表单
本系列的第 1 部分中已经创建了一个非常简单的表单,其中包括一个文本输入字段和一个提交按钮,可以向本地主机上假想的搜索引擎发送请求(如图 1 所示)。这类表单仍然很常见,尽管它通常不是孤立在单独的网页上。
图 1. 非常简单的 Web 表单
非常简单的 Web 表单
这是个很好的起点,我们再来看看 XHTML 和 XForms 代码(清单 1)。XForms 的专用代码用粗体字显示,很容易看到,文档的其他部分是纯粹的 XHTML 1.1 Strict。
清单 1. 起点
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ev="http://www.w3.org/2001/xml-events">
<head>
<title>Search Form</title>
<xf:model>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
</head>
<body>
<h1>Search Form</h1>
<p>
Enter a search string, then click the Search button.
</p>
<p>
<xf:input ref="query"><xf:label>Find:</xf:label></xf:input>
<xf:submit
submission="submit-search"><xf:label>Search</xf:label>
</xf:submit>
</p>
</body>
</html>
增加 XForms 名称空间(使用 xf: 前缀)后,已经有了一个 <xf:model> 块,它声明了名为 submit-search 的提交动作,可以使用标准的 HTTP GET 方法提交指定的搜索字符串。<body>, <xf:input> 和 <xf:submit> 元素中的内容构成了简单的表单,包括输入字段和提交按钮,后者触发 <xf:model> 中声明的动作。
如果愿意的话,可以直接试一试,<xf:input> 和 <xf:submit> 元素的距离、先后或位置没有任何特殊要求,它们可以出现在文档 <body> 的任何地方。表单的输入部件表示与其数据模型分离开来。
由于将使用该文档作为本文中其他 XForms 文档的出发点,这里还提供了 XMLSchema 和 xml-events 的 XML 名称空间声明,XForms 利用这两个辅助标准分别提供标准数据类型和表单事件。
回页首
创建一个简单的模型
XForms 的吸引人的原因之一是其将数据模型从表示中分离出来的方法。再看看清单 1,模型(<xf:model> 块中)本身存在于 XHTML 文档的 <head> 中。
当然,除了一个提交动作之外这个模型完全是空的。它不含任何数据!
不过,先别忙。系统(在这里就是支持 XForms 的浏览器)为您创建了一个(如清单 2 所示),其中包含表单引用的数据字段。
清单 2. 简单表单默认的完整 <xf:model>
<xf:model>
<xf:instance>
<data xmlns="">
<query/>
</data>
</xf:instance>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
显式地包含这种形式的实例为表单额外增加了一层验证;表单控件(比如这个简单表单中的文本字段和提交按钮)所引用的字段必须存在于模型实例之中。引用不存在的实例元素的控件要么不能呈现,要么生成错误消息(取决于 XForms 实现)。
回页首
默认值
如果显式地声明数据实例,可用它来定义默认值,只要将默认值放在字段元素中即可。清单 3 中的模型和清单 2 相同,只不过为查询提供了一个有帮助的默认值(如图 2 所示)。
清单 3. 在 <xf:instance> 中直接包含默认值
<xf:model>
<xf:instance>
<data xmlns="">
<query>One or more search keywords.</query>
</data>
</xf:instance>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
图 2. 在模型实例中包含帮助性的提示或者有意义的默认值
在模型实例中包含帮助性的提示或者有意义的默认值
回页首
隐藏值和隐藏控件
用户触发提交动作时,XForms 发送完整的 XML 文档(数据模型实例)。创建模型实例时可以包含需要的任何数据。
因而不再需要在表单中使用隐藏控件。如果有些数据需要发送到服务器上的表单处理程序,但是又不必显示给用户(或者需要保持不变),那么可以将其添加到模型实例中(如清单 4 所示)。
清单 4. 在实例而不是表单中包含隐藏数据或者常量
<xf:model>
<xf:instance>
<data xmlns="">
<query>One or more search keywords.</query>
<engine-version>2</engine-version>
<results>25</results>
</data>
</xf:instance>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
该例中,<engine-version> 和 <results> 永远不会被表单控件引用,也不会被用户看到(除非用户查看源代码)。这些数据组作为查询的一部分发送给 imaginary-search-engine,imaginary-search-engine 可以利用它们选择搜索引擎和设置返回的结果数。
回页首
加载实例
如果数据模型很大,或者需要向用户隐藏某些数据,可以从外部 XML 文件加载实例(如清单 5 所示)。
清单 5. XML 文件中的简单模型实例
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="">
<query>One or more search keywords.</query>
<engine-version>2</engine-version>
<results>25</results>
</data>
只要让 <xf:instance> 引用具体的实例 URL(如清单 6 所示)就可以了。
清单 6. 引用外部模型实例
<xf:model>
<xf:instance src="search-instance.xml"/>
<xf:submission action="http://localhost/imaginary-search-engine"
method="get" id="submit-search"/>
</xf:model>
由于 <xf:instance> 的 src 属性可以从任何 URL 加载 XML 数据,可以用 XForms 编辑或原样表示任何数据。多数 XForms 实现都要求源文档的 URL 在同一个域中,但部分 XForms 实现也允许您配置一个可信任的站点列表。
回页首
XML 数据中的引用
加载 XML 文件作为数据实例时,有可能无法控制 XML;数据也许是数据库或者其他某个应用程序提供的。如何引用 XML 中的某个元素呢?到目前为止,您还只看到了引用与数据模型匹配的元素。
XForms 表单元素使用的数据模型引用实际上是 XPath 表达式,因此可用 XPath 表达式来引用模型中的任何元素。清单 7 显示了一个扩展后的实例,其中包括一些嵌套元素。
清单 7. 更复杂的数据模型实例
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="">
<query>One or more search keywords.</query>
<engine-version>2</engine-version>
<results>25</results>
<some>
<additional>
<info status="important">Nested info.</info>
</additional>
</some>
</data>
可用 XPath 表达式 some/additional/info(或者 /data/some/additional/info,如果使用绝对路径的话)来访问 <info> 元素,或者用 some/additional/info/@status 访问 <info> 元素的 status 属性。清单 8 显示了可用于编辑该数据文件的表单,在这里假设 Web 服务器支持 PUT 方法(可能需要某种身份验证来保护这种功能)。
清单 8. 编辑更复杂的 XML 数据
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms">
<head>
<title>Search Form</title>
<xf:model>
<xf:instance src="http://localhost/~chrish/data.xml"/>
<xf:submission action="http://localhost/~chrish/data.xml"
method="put" id="submit-edit"/>
</xf:model>
</head>
<body>
<h1>XPath</h1>
<p>
Change the info and status!
</p>
<p>
<xf:input ref="some/additional/info"><xf:label>New
info:</xf:label></xf:input><br/>
<xf:input ref="some/additional/info/@status"><xf:label>New
status:</xf:label></xf:input>
<xf:submit
submission="submit-edit"><xf:label>Save</xf:label></xf:submit>
</p>
</body>
</html>
无论在客户机还是服务器上,对 XForms 来说 XPath 都是一种很好的辅助技术;一旦掌握了 XPath,就可以在表单和表单处理程序中使用它。
回页首
控件的类型
到目前为止,我们只用到了 <xf:input> 和 <xf:submit> 控件,但是 XForms 还提供了很多其他的表单控件。我们来看看这些控件及其在 HTML 中的等价物。
<xf:group>(HTML <fieldset>)用于对表单中的控件进行逻辑分组。清单 9 说明了如何使用 <xf:group> 为三个输入字段加标签。
清单 9. 分组控件
<xf:group>
<xf:label>Personal Information</xf:label>
<p><xf:input ref="lastname"><xf:label>Last
name:</xf:label></xf:input></p>
<p><xf:input ref="firstname"><xf:label>First
name:</xf:label></xf:input></p>
<p><xf:input
ref="address"><xf:label>Address:</xf:label></xf:input></p>
</xf:group>
<xf:input>(HTML <input type="text">)显示一个标准的文本输入字段,我们已经多次用到了它。
<xf:secret>(HTML <input type="password">)显示一个文本输入字段,输入的内容隐藏起来,适用于输入口令或者其他保密数据。<xf:secret> 与文档源代码中的 <xf:input> 完全相同。
<xf:select appearance="full">(HTML <input type="checkbox">)为用户提供一个或多个可选项,允许多选。清单 10 给出了一个例子。
清单 10. 多选控件
<xf:select ref="potato-chips" appearance="full">
<xf:label>Favourite flavours:</xf:label>
<xf:item><xf:label>Dill
Pickle</xf:label><xf:value>dill</xf:value></xf:item>
<xf:item><xf:label>Ketchup</xf:label><xf:value>ketchup<
/xf:value></xf:item>
<xf:item><xf:label>Plain</xf:label><xf:value>plain<
/xf:value></xf:item>
<xf:item><xf:label>Salt &
Vinegar</xf:label><xf:value>snv</xf:value></xf:item>
</xf:select>
<xf:select appearance="minimal">(HTML <select multiple>)用于从菜单或列表中选择一个或多个项,对 appearance 属性使用 minimal 可以在更小的区域中呈现项目列表。
<xf:select1>(HTML <input type="radio">)类似于 <xf:select>,但是只允许用户从列表中选择一项。它可以呈现为一组单选按钮、可滚动的选择区域或者菜单,使用 appearance 属性告诉呈现引擎应该呈现为什么。
<xf:select1> 和嵌套的 <xf:choices>(HTML <select> 和嵌套的 <optgroup>)允许用户从分组列表中选择一项。<xf:choices> 子列表的标签呈现在列表中,但是不能选择。清单 11 显示了一个饮料列表让用户选择,用户也可以从非酒精和酒精饮料中选择。
清单 11. 从多个分组中选择一项
<xf:select1 ref="drink">
<xf:label>Drink:</xf:label>
<xf:item><xf:label>None</xf:label><xf:value>none
</xf:value></xf:item>
<xf:choices>
<xf:label>Soft drinks</xf:label>
<xf:item><xf:label>Juice</xf:label><xf:value>juice
</xf:value></xf:item>
<xf:item><xf:label>Milk</xf:label><xf:value>milk
</xf:value></xf:item>
<xf:item><xf:label>Soda</xf:label><xf:value>soda
</xf:value></xf:item>
<xf:item><xf:label>Water</xf:label><xf:value>water<
/xf:value></xf:item>
</xf:choices>
<xf:choices>
<xf:label>Wine and beer</xf:label>
<xf:item><xf:label>Beer</xf:label><xf:value>beer<
/xf:value></xf:item>
<xf:item><xf:label>Red
wine</xf:label><xf:value>redwine</xf:value></xf:item>
<xf:item><xf:label>White
wine</xf:label><xf:value>whitewine</xf:value></xf:item>
</xf:choices>
</xf:select1>
<xf:textarea>(HTML <textarea>)显示一个多行文本输入字段,如果默认值不合适可使用 CSS 样式控制区域的大小。
<xf:trigger>(HTML <input type="button">)呈现一个动作按钮。按钮没有预定义的行为,因此需要为其附加一个动作,按钮被激活时将触发该动作。清单 12 中的 <xf:trigger> 激活一个 JavaScript™ 函数,名为 calculate()。
清单 12. 调用 JavaScript 函数 calculate() 的按钮
<xf:trigger>
<xf:label>Calculate</xf:label>
<script ev:event="DOMActivate" type="text/javascript">
calculate();
</script>
</xf:trigger>
要注意,这里第一次使用 ev: 名称空间,虽然在前面的基本表单的示例中早已声明。它用于引用标准 XML Events 属性 ev:event,它告诉触发器什么时候激活脚本。
<xf:trigger>(HTML <input type="image">)也可用于为表单添加图像按钮,只需在 <xf:label> 元素中插入 <img> 元素或者使用 CSS 将图像作为元素的背景即可。
如果正在把某些 HTML 表单升级到 XForms 表单,可以使用 <xf:trigger>(HTML <input type="reset">)增加 Reset 按钮(升级规范可能要求“全部功能”,包括无用的 Reset 按钮)。清单 13 说明了如何创建一个表单复位按钮,但是不要在新表单中使用它:最终用户永远不会有意识地单击 Reset 按钮。
清单 13. 实现无用的历史遗留物:Reset 按钮
<xf:trigger>
<xf:label>Reset</xf:label>
<xf:reset ev:event="DOMActivate"/>
</xf:trigger>
<xf:upload>(HTML <intput type="file">)用于实现文件上传。和其他控件相比这个更复杂一点,因为它需要一种特殊的 <xf:submission> 方法:form-data-post(如清单 14 所示)。
清单 14. 使用 <xf:submission> 方法上传文件
<xf:model>
...
<xf:submission action="http://localhost/upload-engine"
method="form-data-post" id="upload"/>
</xf:model>
表单下方的 <xf:upload> 元素看起来类似于 <xf:submit> 或 <xf:input>(如清单 15 所示)。
清单 15. 使用 <xf:upload> 上传文件
<xf:upload ref="upload"><xf:label>Upload a
file:</xf:label></xf:upload>
另外,还有一些 HTML 中不存在的控件。
<xf:output> 允许在文档中增加一些文本值。比如清单 7 中向数据模型增加了 <results> 元素。虽然用户不能修改它,但是可以通过编辑模型来改变它(特别是如果使用外部 XML 文件中定义的模型的话)。可以使用 <xf:output> 元素向用户显示这些信息(如清单 16 所示)。
清单 16. 使用 <xf:output> 显示模型中的数据
<p>
Your search will return a maximum of
<xf:output ref="results"> matches.
</p>
<xf:range> 为用户显示一个范围选择条(slide)或者适合于获得受约束值的其他控件。比方说,可以用三个 range 让用户输入红/绿/蓝中的一个作为突出显示搜索结果的颜色(如清单 17 所示)。
清单 17. 使用范围输入控件
<p>
Keyword highlight:<br/>
<xf:range ref="r" start="0" end="100" step="1"><xf:label>Red</xf:label></xf:range><br/>
<xf:range ref="g" start="0" end="100" step="1"><xf:label>Green</xf:label></xf:range><br/>
<xf:range ref="b" start="0" end="100" step="1"><xf:label>Blue</xf:label></xf:range>
</p>
现在介绍了各种 XForms 输入控件(和一个输出控件),下面来看看各种不同的提交动作。
回页首
基本提交动作
XForms 标准支持通常的 HTML 表单提交方法,但是 HTML 需要 method 和 enctype 来指定提交方法,而 XForms 只需要一个 method。
<xf:submission method="form-data-post" action="url"/> 和 HTML 中的 <form method="post" enctype="multipart/form-data"> 相同,可以按同样的方法在收到 URL 时被处理。
<xf:submission method="get" action="url"/> 和 HTML 中的 <form method="get"> 相同。
<xf:submission method="urlencoded-post" action="url"> 和 HTML 中的 <form method="post" enctype="application/x-www-form-urlencoded"> 相同。
除了和 HTML 兼容的提交方法之外,XForms 还定义了两种新的提交动作,method="post" 和 method="put"。
method="post" 动作将表单数据模型实例作为 XML 文档 post 给接收 URL,适用于 XSLT 或者其他 XML 处理技术。客户机不需要制定编码或者转义,服务器上也不需要特殊处理(除了标准 XML 解析以外)。
method="put" 动作将表单数据模型实例作为 XML 文档 put 给目标 URL。如果服务器支持 PUT 方法,并且允许对目标 URL 使用该方法,该 XML 文档将代替目标 URL 上的文件。可利用该方法现场编辑“任何”XML 文档,只需要通过和后来 put 动作要用到的相同的 URL 加载数据模型实例即可。
纯 XML post 和 put 方法是 XForms 目标的一部分,为数据处理带来了一定程度的灵活性。
回页首
结束语
XForms 提供了一致的、清晰的基于 XML 的数据模型,可以在文档或者页面处理期间加载的外部文件中直接包含任意的 XML。该标准支持现在所有 HTML 表单控件的等价物,并增加了另外两个有用的控件用于范围选择和显示数据。基本 XForms 提交动作包含了原来的 HTML 的提交方法,并增加了两种基于 XML 的方法。本文全面介绍了这些控件,您可以以此为基础开始自己的 XForms 体验。
XForms 学习交流群:38587873/. 欢迎大家入群讨论。