2 XForms导论
XForms是在多年HTML表单经验的基础上设计的。HTML表单组成了电子商务革命的支柱,表现了它们的价值,也显示了许多值得改进的地方。
对比XForms与HTML表单,除了XForms是XML格式之外,其主要区别是分离了收集的数据和收集这些值的控件标记(markup)。通过这样,不仅使得XForms更加容易管理(什么数据提交到哪里一目了然),也更易于表单的重用,因为表单的底层基础部分(数据部分)不再与使用它的页面强制性的绑定。
第二个重要的区别是XForms虽然设计成与XHTML集成,但不再局限与仅是XHTML语言的一部分,而可以集成进其他合适的标记语言。
XForms努力改进了表单的创建、重用、国际化、易用性、可用性和设备无关性。下面对使用XForms的主要优点进行了总结:
强数据类型
提交的数据是强数据类型的,可以使用现有的工具进行检查。这减少了对往返于服务器间的确认的需求而加速了表单填充。
XML提交
这消除了通过定制服务器端逻辑来整合提交的数据到后台应用的需求。接收到的XML实例文档可以被后台应用直接验证和处理。
重用已有的模式(schema)
这消除了重复,并且保证是底层的业务逻辑改变导致的验证(validation)规则更新,不需要在XForms应用中重新创建验证约束
增加外部规则
这使得XForms表单设计者可以超出后台提供的基本约束集。提供额外的约束作为XForms模型的一部分增强了生成的Web应用的整体可用性。
国际化
实例数据使用XML1.0从而确保提交的数据是国际化的。
增强的易用性
XForms分离了内容和表现。用户界面控件包装了所有相关的元数据(例如标签),因此增强了使用不同表现形式(modalities)时应用的易用性。XForms用户界面控件是通用的和设备无关的。
多设备支持
用户界面控件的高层次本质和随之产生的基于目的的用户界面创建方式使得可以是用户交互应用到不同的设备。
脚本的更少使用
通过定义基于XML声明的事件处理器(event handlers)(覆盖了普通用例),大部分XForms文档的大部分可以静态分析,减少了事件处理器对必要的脚本的需求。
2.1 例子
在XForms方式中,表单由两部分组成:一部分描述了表单做什么,称为XForms Model,另一部分描述了如何显示表单。
一个简单的电子商务表单可能显示如下:
很明显,我们要收集代表使用现金或信用卡的一个值,以及如果使用信用卡,卡号和过期日期的值。
这可以在XForms model元素中表示,它通常被包含在XHTML中的head部分。
<xforms:model>
<xforms:instance>
<ecommerce xmlns=”">
<method/>
<number/>
<expiry/>
</ecommerce>
</xforms:instance>
<xforms:submission action=”http://example.com/submit” method=”post” id=”submit” includenamespaceprefixes=”"/>
</xforms:model>
这只是说明了我们要收集三部分信息(注意,我们还没有谈及他们的类型),并使用action属性中的URL提交这些信息。
XForms定义了一个设备无关、平台无关的表单控件集合,这个集合适用于通用的目的。这些控件通过XForms绑定机制绑定到XForms Model上。在这个简单的例子中是使用控件的ref属性。在XHTML中,这个标记通常出现在body部分(注意,我们在这故意漏掉XForms的名称空间前缀):
<select1 ref=”method”>
<label>Select Payment Method:</label>
<item>
<label>Cash</label>
<value>cash</value>
</item>
<item>
<label>Credit</label>
<value>cc</value>
</item>
</select1>
<input ref=”number”>
<label>Credit Card Number:</label>
</input>
<input ref=”expiry”>
<label>Expiration Date:</label>
</input>
<submit submission=”submit”>
<label>Submit</label>
</submit>
注意这个设计的如下特征:
可以绑定表单控件到模型的能力使得把XForms集成到其他宿主语言(host language)简单化了,因为可以使用任何表单控件的标记绑定到模型。
2.2 提供XML实例数据
XForms Processor可以直接提交XML格式的数据,在这个例子中,提交的数据如下所示:
<ecommerce>
<method>cc</method>
<number>1235467789012345</number>
<expiry>2001-08</expiry>
</ecommerce>
XForms处理器通过这个实例数据跟踪部分完成的表单的状态。如例子所示,实例数据的初始值可以提供或为空。instance元素本质上保存了当用户填写表单时更新的XML文档。这使得表单设计者可以完全控制提交的XML数据的结构,包括名字空间信息。当表单被提交时,实例数据被序列化成XML文档。下面是前面的例子的另一个版本:
Model
<xforms:model>
<xforms:instance>
<payment method=”cc” xmlns=”http://commerce.example.com/payment”>
<number/>
<expiry/>
</payment>
</xforms:instance>
<xforms:submission action=”http://example.com/submit” method=”post” includenamespaceprefixes=”#default”/>
</xforms:model>
在这个例子中,提交的数据如下所示:
Submitted Data
<payment method=”cc” xmlns=”http://commerce.example.com/payment”>
<number>1235467789012345</number>
<expiry>2001-08</expiry>
</payment>
这个设计有如下特性:
为了连接实例数据和表单控件,需要改变表单控件的ref属性来指向实例数据中的正确部分,使用如下绑定表达式(binding expression):
Binding Form Controls to Instance Nodes with ref
… xmlns:my=”http://commerce.example.com/payment”
…
<xforms:select1 ref=”@method”>…</xforms:select1>
…
<xforms:input ref=”my:number”>…</xforms:input>
…
<xforms:input ref=”/my:payment/my:expiry”>…</xforms:input>
绑定表达式是基于Xpath[XPath1.0]的,包括使用@符号来指向属性,如上所示。注意,为了展示的目的,前两个表达式使用了XPath上下文节点,这个节点默认是最高层元素(在这是my:payment)。第三个表达式显示了绝对路径。
2.3 值约束
XForms允许在表单填充时检查数据的有效性。在没有明确指定收集到的数据的类型信息的情况下,所有的值都以字符串形式返回,但是,可以在实例数据中设置值的类型。在这个例子中,number应该只接受14到18位之间的数字,expiry只接受有效的月/日期组合。
另外,number和expiry的信用卡信息表单控件只有在method中的”cc”选项被选中时是相关的(relevant),而且在这种情况下是必需的。
通过指定一个另外的XForms组成部分—模型条目特性(model item properties),表达设计者可以在表单中包含丰富的的有效性验证信息。这些信息可以从XML Schemas或者另外的XForms专有的补充(specific additions),如relevant中获得。这些特性(应该指relevant)出现在bind元素中,而Schema约束(应该指type)在XML Schema段中表达,可以在内部或外部,例如:
Declarative Validation with Model Item Properties
… xmlns:my=”http://commerce.example.com/payment”…
<xforms:model>
…
<xforms:bind nodeset=”/my:payment/my:number”
relevant=”/my:payment/@method = ‘cc’”
required=”true()”
type=”my:ccnumber”/>
<xforms:bind nodeset=”/my:payment/my:expiry”
relevant=”/my:payment/@method = ‘cc’”
required=”true()”
type=”xsd:gYearMonth”/>
<xs:schema …>
…
<xs:simpleType name=”ccnumber”>
<xs:restriction base=”xsd:string”>
<xs:pattern value=”\d{14,18}”/>
</xs:restriction>
</xs:simpleType>
…
</xs:schema>
</xforms:model>
注意:
在上面的例子中,因为计算表达式(computed expression)的求值上下文节点是通过绑定表达式(参见 7.2求值上下文)决定的,所以relevant表达式使用了绝对路径XPath符号(以/开始),因此,在上面的第一个bind relevant中的相对节点路径应该是相对于/my:payment/my:number
的。
2.4 一个文档中包含多个表单
XForms处理对一个单独的文档中可以包含的独立表单的数量没有限制。当一个单独的文档包含多个表单时,每个表单需要一个独立的model元素,并有一个id属性,以此可以在包含它的文档中的别处引用它。
另外,表单控件应该指定哪个model元素包含了它们绑定的实例数据。这通过作为绑定属性一部分的model属性来实现。如果没有对绑定元素指定model属性,则使用最近祖先绑定元素的model属性,如果没有,则使用文档中的第一个XForms Model。这个技术叫做’范围解析’(scoped resolution),在XForms中频繁的使用。
下面的例子对电子商务表单添加了一个民意测验。
Adding a poll model
<xforms:model>
<xforms:instance>
…payment instance data…
</xforms:instance>
<xforms:submission action=”http://example.com/submit” method=”post”/>
</xforms:model>
<xforms:model id=”poll”>
<xforms:instance>
<helpful/>
</xforms:instance>
<xforms:submission id=”pollsubmit” …/>
</xforms:model>
另外,下面的标记将在出现在文档的body部分:
Form Controls for poll model
<xforms:select1 ref=”/helpful” model=”poll”>
<xforms:label>How useful is this page to you?</xforms:label>
<xforms:item>
<xforms:label>Not at all helpful</xforms:label>
<xforms:value>0</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Barely helpful</xforms:label>
<xforms:value>1</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Somewhat helpful</xforms:label>
<xforms:value>2</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Very helpful</xforms:label>
<xforms:value>3</xforms:value>
</xforms:item>
</xforms:select1>
<xforms:submit submission=”pollsubmit”>
<xforms:label>Submit</xforms:label>
</xforms:submit>
这里的主要区别是使用了model=”poll”来指定实例。注意,submit通过ID指向了submission元素,不需要绑定属性。
更多的Xforms的例子可以在 附录H 完整的XForms例子中找到。