The remaining detail is how to associate model item properties with particular instance data nodes. The answer is binding, but it's worth being extra clear with terminology: a bind has two ends, one side in the XForms Model, and the other side at a form control. On the bind element within the XForms Model, the nodeset attribute holds the Model Binding Expression. On the other end, in the user interface, is the UI Binding Expression. This end may be bound two ways, using either IDREFs or XPath.
<!-- in the XForms Model --> <xforms:bind nodeset="email" id="mybind" required="true()"/> ... <!-- later in the document --> <xforms:input bind="mybind"...>
This approach is distinguished by the use of the bind attribute on form controls. The main advantage of this approach is that it maintains separation between the model and the view. If the structure of the instance data were to change, only the attributes on the bind elements would need to be updated. In large organizations, form authoring often involves separate teams: a graphic design team to lay out the form, and a systems team to handle the data integration. In such scenarios, IDREF binding provides a perfect interface between content and presentation.
<!-- in the XForms Model --> <xforms:bind nodeset="email" id="mybind" required="true( )"/> ... <!-- later in the document --> <xforms:input ref="email"...>
This approach is distinguished by the use of ref attributes on form controls. Many view this approach as simpler, since it cuts out one level of indirection. It is also more fragile, however, since the XPath expressions to locate nodes appear in two places. If the structure of the instance data were to change, both the attributes on the bind element and the ref attributes on the form controls would need to change.
<!-- in the XForms Model 1 --> <xform:model id="m1"> <xforms:bind nodeset="email" type="my:email"/> ... </xforms:model> <xforms:model id="m2"> <xforms:bind nodeset="search" type="my:query"/> ... </xforms:model> <!-- later in the document --> <xforms:input ref="email" model="m1"...> <xforms:input ref="search" model="m2"...>
When using IDREF binding, this causes no additional problems, since the ID the form control points to is necessarily unique in the document. When using XPath binding, however, additional information is needed. In which model do you find purchaseOrder/items/item? Because of this dilemma, in any document with two or more XForms Models, every XPath-style binding needs an additional attribute, model, to indicate which model is being bound to. By design, each XForms Model is a self-contained unit, and options for cross-model communication are limited.
A common scenario is that a form needs some extra data, perhaps for a calculation. In HTML forms, hidden fields could be used for this. But in XForms, the initial form data is XML, which is already widely deployed. Often, it's not possible to modify existing DTDs and XML Schemas to add new forms-specific elements and attributes to legacy XML. In these cases, it is possible to set aside additional XForms Instances as temporary storage.
On the markup side, this, too, is straightforward—using multiple instance elements:
<!-- in the XForms Model --> <xforms:model> <xforms:instance id="formdata"> <my:root> ... </my:root> </xforms:instance> <xforms:instance id="userid" src="scripts/getuserid"/> ... <xforms:bind nodeset="my:root/..."/> <xforms:bind nodeset="instance('userid')/..."/> ... </xforms:model>
A similar problem to having multiple models occurs when you try to write a XPath expression that reaches across instances. By default, XPath expressions will always point into the first instance. The function instance( ), which takes an IDREF of an instance element, resets the XPath context to a different instance (but always within the same XForms Model).