级别: 初级 崔康 (cuikang@cn.ibm.com), 软件工程师, IBM 窦文敏 (douwm@cn.ibm.com), 软件工程师, IBM
2008 年 12 月 04 日 随着 Web2.0 技术和 RIA 应用的不断发展,XForms 作为下一代电子表单标准得到更加广泛的应用。模型条目特性 (model item property)是 XForms 标准的一个重要组成部分,用户通过它实现对数据节点的约束,包括动态赋值、有效性检查等,确保前端数据的有效性。本文通过实例向用户详细的介绍了如何使用 XForms 提供的模型条目特性设计高质量的电子表单。
XForms 简介
XForms 是 W3C 下一代电子表单标准,是下一代基于 web 的数据处理技术,目前正式版本是 1.0 。 XForms 在吸收 HTML 经验和教训的基础上设计了一种新的平台无关的标记语言,为 Web2.0 时代的电子表单解决方案提供了完善的支持,最主要的两个优点是:一是将数据和表单控件分离,有效地实现了表单的复用和底层数据的灵活性;二是 XForms 的宿主语言是无限制的,XForms 虽然设计成与 XHTML 集成,但不局限于仅是 XHTML 语言的一部分,而可以集成进其他合适的标记语言。可以使用 XForms 容易的创建更丰富、更动态的设备无关的表单。
模型条目特性概述
电子表单的数据约束机制是指在一个表单中,其每个控件底层所代表的实际业务数据的控制属性,例如,是否只读、是否是纯数字格式、是否是动态计算值等等。通过对电子表单定义适当的数据约束来确保数据的有效性,从而保证系统的运转。
模型条目特性(model item property)是对实例数据节点的基于 XForms 的注解,带有约束的实例数据节点称为模型条目。模型条目特性是 XForms 标准的一个重要组成部分,用户可以使用它通过更加直观的声明方式定义丰富的有效性信息,实现对实例数据节点的约束,包括动态赋值、有效性检查等,确保前端数据的有效性。
因为数据与表现分离,XForms 表单支持多层次的数据有效性验证,既允许在服务器端验证,也允许在客户端验证,这样在保证用户输入的有效性的同时一定程度上杜绝了数据的恶意篡改。
在 XForms 中,模型条目特性是可以通过 bind 元素绑定到实例数据节点的信息集,相对的,Schema 约束只针对来自于已有的数据类型的 XML Schema 约束。一个模型条目特性可以是计算表达式或固定的静态值。对于固定的静态值,XForms 处理器只对其求值一次。计算表达式是 XPath 表达式,定义了动态的特性,例如不同数据条目之间的依赖关系;在需要时,XForms 处理器要对计算表达式进行重新计算求值。有些模型条目特性具有继承性,这种情况下,通过结合实例数据的祖先节点的特性和实例数据节点的特性来确定该特性的值。下面的章节将通过一个例子详细地介绍如何在表单中应用模型条目特性。
实例背景介绍
本文选用了一个网上书店中图书信息管理的表单作为例子,随着信息技术和物流系统的发展,类似于在线购物的网站层出不穷,作者通过一个典型的商品信息管理页面的实现,阐述 XForms 的数据约束机制,读者可以从中体会采用 XForms 电子表单的简洁和功能完备性。图书信息实例(instance)如清单 1 所示。
清单 1. 图书信息实例
<xforms:instance xmlns="" id="instance1">
<bookInfo>
<ID>NO10001</ID>
<name/>
<amount/>
<price/>
<hasDS/>
<discount/>
</bookInfo>
</xforms:instance>
|
图书信息管理的表单如图 1 所示。本文中使用的完整表单详见下载部分,可以使用 Lotus Forms Viewer 3.5 或 Lotus Forms Webform Server 3.5 来打开该表单。
图 1. 图书信息管理表单
其中表单中每一个控件对应的字段的含义如表 1 所示。 表 1. 表单字段列表
| 字段名 | 描述 | | Book ID | 图书唯一标识符,只读属性 | | Book name | 图书名,必填项 | | Book amount | 图书库存数量,必须是非负整数 | | Book price | 图书原价,double 数据类型 | | The Book has discount ? | 由图书信息管理人员选择该书是否打折 | | Book discount | 如果该书打折,则该控件会显示并计算一个默认折扣额,用户可以修改该折扣 |
类型约束—— type 特性
type 模型条目特性可以用于元素和元素的属性,但是它不能应用于包含子元素的实例节点。数据类型可以来自于 simpleType 定义或通过 complexType 定义的 simpleContent 。如果不能获得指定的数据类型的描述,则使用默认的数据类型 xsd:string 。该数据类型约束不能阻止通过控件或 XForms 动作对数据节点输入无效值。
例如,在商品信息管理页面中,通常会要求用户输入的商品价格为数字,这就可以通过 type 特性来约束,如清单 2 所示。
清单 2. type 特性示例
<instance>
……
</instance>
<xforms:bind nodeset="price" type="xsd:double"/>
|
在本例中,数据约束的对象是 price 节点,当商品价格对应的表单控件的输入不是数字时,会提示出错。
只读约束—— readonly 特性
readonly 描述一个节点的内容是否是可修改的,其有效值是可以通过 boolean() 转化成 XPath boolean 的表达式,其默认值是 false() 。如果一个实例节点的祖先节点的 readonly 特性是 true,则该节点也是只读的。当 readonly 特性为 true 时,不能通过模型条目特性系统外的任何手段修改该节点(但可以通过 calculate 来修改),即禁止通过 submission、表单控件、XForms 动作和 DOM 接口访问来修改此节点,同时禁止插入或拷贝新节点到只读的父节点,删除或替换只读节点的子节点等。例如,在商品信息管理页面中,通常会由系统根据规则生成商品的 ID,用户不可以修改 ID 的值,如清单 3 所示。
清单 3. readonly 特性示例 1
<instance>
……
</instance>
<xforms:bind nodeset="ID" readonly="true()"/>
|
通过对 ID 节点设置 readonly 特性,禁止通过任何手段修改该节点的值。
此外,可以通过 readonly 特性来实现默认值和用户输入的组合。如清单 4 所示。
清单 4. readonly 特性示例 2
<instance>
……
</instance>
<xforms:bind nodeset="discount"
calculate="choose(.='',../price*0.05,.)"
readonly="false()"/>
|
通过上面的约束,图书信息管理人员可以任意修改折扣值。在图书信息管理人员输入折扣值之前,calculate 会自动计算一个默认值:price*0.05 。
必填项约束—— required 特性
required 特性描述了一个值在实例数据被提交前是否必须是非空的,其有效值是可以通过 boolean() 转化成 XPath boolean 的表达式,其默认值是 false() 。该模型条目特性并不阻止表单控件和 XForms 动作将数据节点设置为空字符串。例如,在输入商品信息时,通常会要求商品的名称必须是非空的,如清单 5 所示。
清单 5. required 特性示例
<instance>
……
</instance>
<xforms:bind nodeset="name" required="true()"/> |
在该实例中,数据约束的对象是 name 节点。 required 特性为 true 表示必须提供 name 的值。
相关性约束—— relevant 特性
XForms 标准中的相关性指的是该表单元素是否与某业务逻辑相关,即是否有存在的必要。相关性约束根据 XPath 表达式动态判断某些控件是否应该显示或者允许用户输入,如果实例数据节点的 relevant 特性为 false,则提交时不包含该节点。例如,在商品管理页面中,有时会对某些商品定一定数额的折扣,只有用户确定商品打折时,才需要用户输入折扣值,这样的业务需求就可以采用 relevant 特性,如清单 6 所示。
清单 6. relevant 特性示例
<instance>
……
</instance>
<xforms:bind nodeset="discount"
relevant="../hasDS='true'" />
|
在本例中,数据约束的对象是 discount 节点,relevant 提供的表达式 ../hasDS='true',只有当图书信息管理人员确定有 discount 时,数据节点 discount 对应的控件才会显示给图书信息管理人员。
计算性约束—— calculate 特性
计算性约束提供一个 XPath 表达式来动态计算某节点元素的值。该特性为表单的设计者提供了一个根据表单其他元素的值动态计算某特定元素值的方法。例如,在商品管理页面中,可以根据商品的价格为商品计算一个默认的折扣值,这可以通过 calculate 特性实现,如清单 7 所示。
清单 7. calculate 特性示例
<instance>
……
</instance>
<xforms:bind nodeset="discount"
relevant="../hasDS='true'"
calculate="choose(.='',../price*0.05,.)"
readonly="false()"/>
|
在本例中,数据约束的对象是 discount 节点,calculate 的表达式是 choose(.='',../price*0.05,.),如果图书信息管理人员没有指定折扣值,则会计算一个默认的折扣值,通过 calculate 就可以计算出折扣额度并显示给图书信息管理人员。
断言约束—— constraint 特性
断言约束类似于编程语言中的断言语句,constraint 特性根据设计者提供的 XPath 表达式判断某特定节点值是否符合业务逻辑,例如长度是否小于 14 位等,在本例中,商品信息管理页面的中商品数量必须大于等于 0 。这可以通过 constraint 特性实现,如清单 8 所示。
清单 8. constraint 特性示例
<instance>
……
</instance>
<xforms:bind nodeset="amount" constraint=".>=0" />
|
在本例中,数据约束的对象是 amount 节点,constraint 表达式是 .>=0,当用户向商品数量对应的控件输入负数时,会提示出错。
其他约束
除了上面详细介绍的五种模型条目特性,还可以为 XForms 实例数据节点定义 p3ptype 特性。 p3ptype 特性将 P3P 数据元素绑定到实例数据节点,表示该节点收集的数据的特殊类型。可以使用该信息来改进用户使用表单的体验,例如通过提供已知数据来减少用户输入。下面的例子将一个 P3P 类型信息绑定到 first-name 节点。
清单 9. P3P 特性示例
<instance>
<my:person-name>
<my:first-name />
<my:last-name />
</my:person-name>
</instance>
<bind nodeset="my:first-name" p3ptype="user.name.given"/>
|
另外,还可以使用 XML Schema 数据类型系统来约束 XForms 模型收集的数据值。用户可以定义自己的 XML Schema,该 schema 可以是内联的或外部的。然后用 xsi:type 或 bind 将该类型约束绑定到实例数据节点。这样,XForms 作者可以灵活的扩展外部 schema 。如下面的例子所示。
清单 10. Schema 约束示例 1
<xs:simpleType name="nonEmptyString">
<xs:restriction base="xsd:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
|
上面的 XML 片断使用 XML Schema 定义了新的类型 nonEmptyString 。
下面的语句使用 xsi:type 将 first-name 节点定义为 my:nonEmptyString 类型的。
<my:first-name xsi:type="my:nonEmptyString"/>
下面的 XML 片断使用 XForms bind 将类型信息绑定到 first-name 节点。这样,XForms 作者可以灵活的扩展外部 schema 。
清单 11. Schema 约束示例 2
<instance> <my:first-name />
</instance>
<bind type="my:nonEmptyString" nodeset="/my:first-name"/>
|
使用模型条目特性的注意事项
结束语
本文对 XForms 的数据约束机制做了探讨,采用网上书店中图书信息管理的示例阐述了如何通过模型条目特性为表单定义丰富的数据约束信息,体现了 XForms 标准在 Web2.0 时代的易用性和功能完备性。
下载 注意: - 图书信息 xfdl 文件!
参考资料
作者简介  | |  | 崔康,现就职于 IBM 中国软件开发中心,主要从事 Web 应用性能测试方面的工作,感兴趣的领域包括 Web 性能诊断与调优、Java 虚拟机等。 |
 | |  | 窦文敏,IBM CDL 软件工程师,主要从事 IBM Lotus Forms 的测试工作。对XML、Web 技术、软件过程和软件测试有浓厚的兴趣。 |
对本文的评价
|