You are reading O'Reilly XForms Essentials by Micah Dubinko. (What is this?) - Buy XForms Essentials Online

What to Submit

XML comes in trees, but sometimes trees need to be pruned. For situations where less than the full tree of instance data is needed for submission, XForms defines ways to reduce the amount of XML that gets selected for submission.

One of the most powerful techniques for managing complexity is to divide and conquer using multiple XForms Models. For example, if a web page has one form for a search tool and another to register for a newsletter, these should be in separate model elements. When arranged that way, each XForms Model will have separate instance data to be submitted.

Another common case is when temporary data, such as a lookup table, is needed during form processing but not during submission. Using multiple models can help here, too, but the strong separation between XForms Models can get in the way. Another option is to use multiple instances, which can use either inline or remote XML, within the same model. A special XPath function, instance( ), provides easy access to other instances (XPath data models, to be specific), as long as they are part of the same XForms Model.

In this example, the primary instance data, which the author intends for submission, is given the identifier submitme. The secondary instance data, loaded from a separate XML document and given the identifier taxrate, contains a single element such as <tax>0.725</tax>, containing a decimal tax rate. By replacing this file at any time, a new tax rate can be used in the form, thus helping separate business rules from the rest of the form.

<xforms:model>
  <xforms:instance id="submitme">
    <my:item>
      <my:listprice>14.00</my:listprice>
      <my:tax/>
    </my:item>
  </xforms:instance>
  <xforms:bind nodeset="/my:item/my:tax" calculate="../my:listprice * instance('taxrate')"/>
  <xforms:instance id="taxrate" src="taxrate.xml"/>
</xforms:model>

In this example, the calculate expression multiplies two values. One is ../my:listprice, which refers to an element node, from which a numeric value is taken. The other is instance('taxrate'), which returns the top-level element node from the instance data associated with the ID taxrate. The result is placed in the element node at /my:item/my:tax.

Once a particular instance document is selected, XForms still provides additional ways to prune the XML tree. One way is to specify a subtree of the instance data that gets submitted, using either the ref attribute (XPath expression) or bind attribute (IDREF to a bind element).

Finally, any node that has a relevant property that evaluates to false will not be present in the submitted data. A moment of thought will show that once a node is lopped off the tree in this way, all descendent nodes (attributes, text, child elements, etc.) will also be gone, regardless of their individual relevant property

Sometimes, an author might want something to be non-relevant for UI purposes, but not want the data excluded from the XML. In the following example, the spouse element is only relevant when the user has a spouse; but since the submitted XML needs to be DTD-valid, the spouse element needs to be submitted, even if empty.

In Example 8.1, “Submit processing of relevant nodes ”, during normal processing, the only part of the relevant expression that matters is ../my:hasspouse. This causes a form control bound to my:hasspouse to get rendered only when the user has indicated that he or she actually has a spouse. During submit processing, however, the setvalue action sets the flag in the secondary instance data to 1, causing the earlier relevant expression to always be true. As a result, the spouse element will not be excluded from the submitted XML. Note that in a real-world form, a listener for xforms-submit-error events targeted to the model should be included, to set the flag back to after an unsuccessful submission attempt.