VIEWS: 15 PAGES: 18 POSTED ON: 12/30/2012
XForms Training Materials ¶ Learn how to build XForms for JavaRosa Set up your computer to build and test XForms ¶ Follow these instructions to install Notepad++, the sun wireless toolkit and the javarosa validator Install Notepad++ ¶ For the first JavaRosa Xform training day, we used Notepad++ as the XML text editor. Here we've included the steps for installing it, though any text editor can be used for editing XForms 1. Install Notepad++ on your machine 2. Install the XML Tools plugin from the Notepad++ download page. Note that to install you will have to put all of the DLLs from the ext_lib directory in the Notepad++ directory (usually C:\Program Files\Notepad++), then copy the xml tools DLL to the plugins directory (C:\Program Files\Notepad++\plugins). 3. Once everything is installed, start up Notepad++. From the Plugins menu, there should be an option for XML Tools. We have found it useful to tick "Enable XML syntax auto-check" and "Tag auto- close". Also useful is using "Pretty print (XML only - with line breaks)". This will fix all of the indentation of your XML/XForm to make it more readable JavaRosa XForm Validator ¶ 1. To avoid having instructions in multiple places, please follow the JavaRosa XForm Validator setup instructions to both install and configure the validator software. Reference material on XForms ¶ What are XForms? ¶ "XForms" is a format for creating forms/questionnaires in XML. XForms are similar to forms in HTML, and are meant to be the next-generation replacement for HTML forms. XForms are much more powerful than HTML forms. An XForm is an XML document that describes your form, including what questions to ask (including the type of question and the question's caption or prompt), restrictions on the kinds of answers you can enter, and what you want your final data to look like. You author your XForm by hand in an XML editor. XForms are read and filled out by an XForms client, which presents the questions to a user and lets them enter answers, much like you use a web browser to fill out HTML forms. The XForms client we have built and use is JavaRosa. XForms is a very complicated specification; JavaRosa only supports a simple subset of XForms, but this subset is getting more powerful all the time. JavaRosa also supports some customizations beyond the original XForms spec, specific to the needs of mobile users. What is XML? ¶ XML is a generic mark-up language for adding meaning to text. It is very similar to HTML, but is more generic and has stricter requirements. In fact, XHTML is an XML version of HTML. XML is simply tags that surround text and other tags. The types of the tags used and their hierarchy add meaning to a document. The tags you use can be named anything you want (this is the major different between HTML, which has a set of allowed tag names). A collection of tag names, along with rules about how they can be used and what they mean is called a schema. XForms is an XML schema. XHTML is another schema. In fact, the submitted data of your XForm is also an XML schema, different for every form. XML Basics: Tags can be self-closing (<tag />) or come in opening and closing pairs (<tag></tag>). Standalone tags like in HTML (a <br> that is never closed by a corresponding </br>) are not allowed. Paired tags can have text or other tags inside them (<tag>some text <another-tag /></tag>). Which tags can appear inside other tags is determined by the schema. Tags must be closed in the reverse order they were opened (<a><b></b></a>) (<a><b></a></b> is invalid XML) The entire document must be enclosed within a single tag. This is called the top-level element Tags can have attributes (<tag attribute="attribute value" another-attribute="value 2" />) Certain special characters must be escaped when used in text or attribute values: < must be replaced with <, > with >, and & with & Tags can belong to a namespace, and multiple namespaces can be used within a single XML document. Namespaces let us use multiple XML schemas in a single document without conflicts, as two different schemas may use the same tag name. A namespace is simply an abbreviation (that we choose ourselves in our XML document) that is assigned to a given XML schema. For example, if we declare xf as our namespace for the XForms XML schema, XForms tags will look like <xf:input> and <xf:bind>. An XML document can have one default namespace, for which you don't need to use the namespace prefix in the tags for that schema. Typically, we make XForms our default namespace, as most of the tags in our document are XForms tags. What is JavaRosa? ¶ JavaRosa is an XForms client for mobile phones, written in J2ME. JavaRosa is an application platform that programmers can customize to suit different projects. There is no one 'JavaRosa application'. But at the heart of every JavaRosa application is the XForms engine, which is an activity that reads your XForms, presents the questions to a user and lets them enter answers, and saves or sends off the final data for your form. JavaRosa is open source and is developed by members of the OpenRosa consortium around the world, with development teams in Tanzania, Kenya, South Africa, Uganda, Bangladesh, Pakistan, and USA. Anatomy of an XForm ¶ The skeleton of an XForm looks like this: <h:html xmlns="http://www.w3.org/2002/xforms" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jr="http://openrosa.org/javarosa"> <h:head> <h:title>[form title]</h:title> <model> <instance> [define the schema of your resulting data here] </instance> [define restrictions on your data (such as data types, range constraints, and skip logic) with bindings here] </model> </h:head> <h:body> [add controls that describe your questions here] </h:body> </h:html> The XForms schema is meant to be embedded in some other kind of XML schema, so note how our XForms tags are placed inside a skeleton HTML document. Also note our various namespace declarations at the top of the document, and how XForms is the default namespace. The XHTML namespace is given the prefix h. The namespace for JavaRosa customizations is given the prefix jr. There are three main components to an xform: 1. The instance The output of a filled-out XForm is itself another XML document. The schema of this XML document is custom to your XForm. You create a skeleton of this XML document and place it inside the <instance> tag. Questions refer to various parts of the instance and place their answers there as they are filled out. When your form is complete, the instance can be saved as a complete, self-contained XML document, and submitted from the phone to remote servers. Since the instance must be a complete XML document on its own, and an XML document must contain one, and only one top-level element, the <instance> element must contain only one child element. Sample instances: <patient xmlns="http://commcare.org/patient-registration-0.1"> <name /> <sex /> <age /> <symptoms /> </patient> <water-quality-survey xmlns=""> <location /> <well-id-number /> <measurements> <ABT /> <CC6 /> <PSM /> </measurements> <comments /> </water-quality-survey> Once filled out, these instances may look like: <patient xmlns="http://commcare.org/patient-registration-0.1"> <name>DREW ROOS</name> <sex>male</sex> <age>25</age> <symptoms>cough fever rash</symptoms> </patient> <water-quality-survey xmlns=""> <location>Mlandizi</location> <well-id-number>45</well-id-number> <measurements> <ABT>0.73</ABT> <CC6>4.32</CC6> <PSM>B</PSM> </measurements> <comments>QUALITY IS GOOD; WATER LEVEL LOW</comments> </water-quality-survey> Note how it's a good idea to make the tag names in your instance as descriptive as possible. Also note that since the top-level tag for your instance is the top-level element of an XML document, it should have an xmlns attribute, even if you leave it blank to start. 2. The bindings Bindings let us attach restrictions to the type of data that may be entered into into the instance. The restrictions may be: Data types, for example, indicating that a given question is meant to store dates, so only dates will be allowed as answers to that question. This may also affect how the question appears to the user (see 'controls'). Another kind of data type is restricting answers to numbers only. Skip logic: only allowing a question to be answered if another question has a certain value (e.g., only asking 'is patient pregnant' if 'sex' is female) Required: requiring that a question be answered before you can complete the form Range constraints: limiting the kinds of answers that may be accepted (e.g., rejecting body temperatures over 50 and under 30) Bindings are defined via a <bind> tag. The binding references a single tag in the instance via an XPath expression, and then defines the various restrictions on that question. Every question has it's own binding. Not every question needs a binding, though, such as if it uses the default data type (text) and has no other restrictions. The instance and the bindings together comprise the XForm model. 3. The controls The controls define the questions that the user actually sees. Each question presented to the user is its own control, and the user sees the questions in the same order listed in the XForm. A control is either an <input>, <select>, or <select1> tag. <input> is used for free-entry questions, such as text, numbers, and dates; <select1> is used for multiple-choice questions where you can pick only one choice; <select> is used for multiple-choice questions where you can pick many choices. A control must define the following things: Where in the instance the answer is stored (via an XPath expression) The caption or prompt of a question For multiple choice questions, the available choices and their captions Note that most of the properties you associate with a question, such as whether it's required, the data type (text vs. numeric vs. date), and skip logic, are actually defined in the binding. The control and the binding have no direct knowledge about each other. The only thing that links a control and its binding is that they refer to the same destination tag in the instance. What is XPath? ¶ XPath is a mini-language for referring to nodes (tags) within an XML document. In XForms, we use XPath to address specific nodes/questions in the instance. The basic format of an XPath path is /a/b/c, where a refers to the top-level element of the XML document (which must be named <a> in this example), b refers to the tag <b> that is an immediate child of <a>, and c refers to the tag <c> which is an immediate child of <b>. To use the sample instance above, /patient/name and /water-quality-survey/measurements/ABT are valid XPath paths. XPath paths come in two varieties: absolute and relative. The paths above, and any path that starts with /, are absolute. This means to start searching for your node at the very top of the XML document. If there is no beginning slash, the path is relative, which means you begin searching from some node (called the 'context node') that varies depending on the context where you're using the path. In most cases in an XForm, the context node of a relative path is simply the top-level element of the instance. This means that we could shorten the paths above to simply name (as /patient is assumed as the context node) and measurements/ABT (where /water-quality-survey is the context node). The only exception is inside a binding when dealing with range constraints and skip logic. Here, the context node is the instance node that the binding refers to. There are two special kinds of relative paths that are useful in this situation: . refers to the context node itself .. refers to the parent tag of the context node We will see more examples of these as we cover constraints and skip logic. There is also the more general concept of an 'XPath expression', in which you can do computations or comparisons on the values of nodes identified by paths. The details of XPath expressions are an advanced topic we won't cover here, but we use XPath expressions to define the conditions for constraints and skip logic, so you will see some examples there. Basic controls ¶ As said before, there are three basic XForms controls. Use <input> for free-form questions such as text, number, or date. The format of the control is as follows: <input ref="name"> <label>What is your name?</label> </input> The value of the ref attribute is the path to the instance node where the answer to this question is stored. The content inside the <label> tag is the prompt presented to the user. When the question is answered, the value that gets stored in the XML instance is the literal text or number that was entered, or for dates, the date formatted in XML date format (e.g., 2009-03-02). Use <select> and <select1> for multiple choice questions (<select> for multi-select and <select1> for single-select). The format for both controls is identical: <select ref="symptoms"> <label>What are your symptoms?</label> <item> <label>Cough</label> <value>cough</value> </item> <item> <label>Rash</label> <value>rash</value> </item> <item> <label>Fever</label> <value>fever</value> </item> <item> <label>Itching and Peeling</label> <value>itch-peel</value> </item> <item> <label>Other</label> <value>other</value> </item> </select> ref and the first <label> are the same as for <input>. The difference is that now we define the choices as well. Each choice is defined in its own <item> tag. An <item> contains both a <label> and a <value>. Like <label> before, this defines the captions that the user will see for this choice. <value> defines an internal code for the choice that will be stored in the XML instance if this choice is selected. As such, it should be human-readable, but short and terse. For a multi-select, the <value>s of all selected choices will be stored in the instance, as a list separated by spaces. Clearly, <value> should not contain spaces! (or much punctuation at all, for that matter). Bindings ¶ The format of a binding is: <bind nodeset="name" ... /> The nodeset attribute is just like ref for controls; it says which instance node this binding applies to. In addition to nodeset, the binding will contain one or more attributes to accomplish various goals, which we will now cover. Data types ¶ To restrict a question to a certain type, add the attribute type="[datatype]" to the binding, where [datatype] is string for text, int for integers, decimal for numbers with decimal points allowed, and date for dates. string is the default, so you don't need the type parameter for text questions or multiple- choice questions. Required questions ¶ To make a question required, add the attribute required="true()" to the binding (note the parenthesis). Skip Logic ¶ To make a question conditionally skipped based on the value of another question, we use the relevant attribute. We add this to the binding of the question that is conditionally skipped, not the question whose answer decides whether the other question is skipped. This is an important distinction that is confusing for many. For example, if we have a question A that decides whether questions B, C, and D are skipped, the bindings for B, C, and D will each have a relevant attribute that references the value of A. The value of the relevant attribute is an XPath expression that references the values of previously- answered questions. If this expression evaluates to true, the question will be shown; if it evaluates to false, it will be skipped. Here are some examples. Consider the following instance: <patient> <name /> <age /> <sex /> <pregnant /> <in-school /> </patient> <bind nodeset="pregnant" relevant="/patient/sex = 'f'" /> <bind nodeset="in-school" relevant="/patient/age >= 4 and /patient/age <= 25" /> .... <select1 ref="sex"> <label>Sex of patient</label> <item><label>Male</label><value>m</value></item> <item><label>Female</label><value>f</value></item> </select1> In this example, the 'are you pregnant' question is only asked if the 'sex' question was answered 'female'. The 'are you in school' question is only asked if the patient is between 4 and 25 years old. Important things to note: The <= and >= comparisons for age had to be escaped into <= and >= We only use absolute paths inside the relevant attribute; this is because the context node is now whichever node is specified in the nodeset attribute of the <bind>. Using relative paths like sex and age would no longer give us what we want! When checking for a certain answer of a multiple-choice question, we compare against the <value> for that choice, as this is what is stored in the instance. Also, we compare it as a string, so we must enclose the literal value (f in this case) in single quotes. Conditions like these can get quite complicated, so it's best at first to try to adapt from existing examples. If you have any further questions, ask one of the instructors. It is also important to fully test all possibilities when building your form to make sure your condition works as expected. Range Constraints ¶ To limit the range of acceptable values for a question, we use the constraint attribute. The value of the attribute is an XPath expression that is evaluated after the question is answered. The expression must evaluate to true for the answer to be accepted. If it evaluates to false, the user will be notified and forced to enter a different answer. In order to be useful, the expression must actually reference the node to which the constraint (and the binding) applies. This is where the . relative path comes in useful, as it always refers to the node that the binding applies to (the node we are constraining). Examples: <bind nodeset="body-temperature" constraint=". > 32 and . < 45" /> <bind nodeset="birth-date" constraint=". <= today()" /> If the value is outside of the allowed ranges, the constraint expression will be false, and the answer will be rejected. By default, the user will receive a generic 'outside of allowed range' alert. You can change this to a custom alert by also adding the jr:constraintMsg parameter. For example: <bind nodeset="birth-date" constraint=". <= today()" jr:constraintMsg="Birthdates in the future are not allowed" /> Default values and Hidden questions The XML instance is not required to be empty by default. The nodes in the instance may in fact contain data. This data will be used as default values for the questions. Example: <patient> <district>DAR ES SALAAM</district> <name /> <sex /> <age /> <symptoms /> </patient> DAR ES SALAAM will now be used as the default value for the 'district' question, but it may still be changed when the user answers the question. If they enter something different, the new answer will be written back to the instance, overwriting the default. Default data in the instance must be validly formatted for the data type of the associated question. This means that for date questions, the date must be in YYYY-MM-DD format, and for multiple-choice questions, the data must correspond to the <value>s for that question's available choices. In general, the default value must be in the same format you would get if you had entered that value when answering the question itself. Failure to do so may cause your form to crash. It is also possible to have default data in the instance, and no question control that actually references that data. This makes it impossible to change that data when filling out the form. This is how XForms does "hidden" questions (like you can do in HTML forms). This is useful for meta-data like form version – data that should change rarely throughout your deployment and that the user doesn't need to know about. Submission ¶ Traditional XForms (and HTML forms) let you describe how and where to submit the form as part of the XForm definition itself. The XForms spec itself supports this, however currently JavaRosa doesn't. In the JavaRosa platform, where, when, and how you submit your completed forms is defined through configuration settings at the application-level, not through any directives in the XForm itself. This will probably change in the future, with us supporting both methods. Sample Forms¶ These forms illustrate the process of building an XForm. It starts with the most basic skeleton form with no questions, and gradually adds more capability with each revision. Form 1: basic skeleton form with no questions; use this as the template for each form you create Form 2: add 3 basic questions, including free-entry and multiple-choice Form 3: add basic bindings and data types Form 4: add default values Form 5: add hidden fields Form 6: add required questions Form 7: add data constraints Form 8: add skip logic XForms as supported by JavaRosa ¶ Note: this page assumes advanced proficiency with xforms and JavaRosa. If you're looking for information on how to write forms, please consult our introductory guide. The full XForms specification is large and complex. JavaRosa runs on mobile devices that have limited resources and non-standard UI. Consequently, we only support a limited subset of the xforms spec, and in some cases only support it in idiosyncratic ways. This page attempts to precisely document which portions of the xforms spec are supported in JavaRosa. JavaRosa is an actively evolving application, so if a certain feature is not supported, that may simply be because no one has had time to implement it yet. Expect the JavaRosa xforms engine to grow ever-more powerful over time. Also, if there is a certain capability you want that is missing, notify the JavaRosa developers, or if you have the means, add it yourself! However, given xforms' origins in rich web clients, and mission to support application-like user experience, certain xforms features are simply inappropriate for a mobile platform, and will not be implemented. Furthermore, JavaRosa has a defined a number of additions/customizations to the xforms spec, which address shortcomings and improves the xforms experience on mobile devices. These custom constructs are supported only by JavaRosa, and have been created when no xforms idiom is able to handle our desired use case, or the 'proper' xforms way of doing it is too complicated and resource-intensive. When customizations have been added, we have attempted to keep them as 'xform-y' as possible. XForms 1.0 specification JavaRosa XForm Validator - a tool to test if your XForm is JavaRosa-compliant JavaRosa XForms ¶ Overall form structure ¶ XForms elements are intended to be hosted inside some other XML schema. JavaRosa XForms typically use XHTML for this purpose. We enclose the XForms model inside the html <head> tag, and the XForms controls inside the html <body> tag. We also use the html <title> and <meta> tags to describe meta-data about the form, including form title, form ID/descriptor, and form version. User controls ¶ XForms defines the following user controls: Control Supported <input> fully supported in JavaRosa for data types text, integer, decimal/fractional number, and date. other data types not yet supported <select1> supported in JavaRosa, except no support yet for dynamic choice lists (<itemset>), or 'open' selections (where you can manually enter in a choice not in the list) <select> supported in JavaRosa, except no support yet for dynamic choice lists (<itemset>), or 'open' selections (where you can manually enter in a choice not in the list) <secret> no support yet in JavaRosa. easy to implement but no compelling use case thus far <textarea> no support yet in JavaRosa. easy to implement but <input> with type text does just as well <range> no support yet in JavaRosa <submit> no support in JavaRosa, and probably never will be (form submission is handled at the application level) <upload> limited support for image and audio capture; very application/use case specific. expect development on this in the future <output> limited support for specific use cases, but not generally usable. expect development on this in the future <trigger> extremely limited support for specific use cases, but not generally usable. unlikely that comprehensive support for this will be added Within the user controls, xforms defines the following descriptive tags: Tag Supported <label> fully supported <hint> parsed, but not currently used in the form entry UI <help> no support currently <alert> no support currently (I'm unclear on what situations this tag is even for) You can alter the look and feel of an xforms control through the appearance attribute, but JavaRosa doesn't currently support this in any meaningful way. Instance and Model ¶ JavaRosa does not currently support multiple <model>s or multiple <instance>s. In the instance, you can bind questions only to leaf nodes. Instance nodes may contain attributes, and these attributes will be preserved when the form is submitted, but you cannot currently bind any question to an attribute (e.g., <bind nodeset="patient/@id" ... /> is not supported) or access the value of an attribute in an expression. The top-level instance node is recommended, but not required, to have an xmlns attribute identifying the schema of the form instance. Bindings ¶ There is no support for nested bindings. XForms defines the following binding attributes: Binding Supported supported, though supported data types vary by control. namespace prefix for the type may be type omitted (e.g., date will be accepted in addition to the formally correct xsd:date) readonly fully supported, but see support caveats for xpath expressions required fully supported, but see support caveats for xpath expressions relevant fully supported, but see support caveats for xpath expressions fully supported, but see support caveats for xpath expressions. also supports a custom attribute constraint jr:constraintMsg to provide a custom alert to the user when the constraint is violated. (maybe this is what <alert> is for?) calculate no support yet p3ptype will never be supported We also support two custom bind parameters, jr:preload and jr:preloadParams, used for defaulting in data when the form is loaded. Normally you'd just hard-code the data in the instance to default it, but this isn't possible for dynamic data that you want to pre-load into your instance. Thus, we have these parameters to call out to various preloaders. A preloader is a Java handler that is registered with the xforms engine and provides certain kinds of data. The jr:preload parameter identifies which registered preloader to call out to; the jr:preloadParams parameter passes information to the preloader about what kind of data you want back. Some built-in preloaders include: Preloader Used for date used for getting dates, like today's date, yesterday, tomorrow, the 5th previous Wednesday, etc. timestamp used for getting timestamps, like when the form was opened, when it was completed property used for fetching data stored in JavaRosa properties, like device ID context used for fetching data from the current application context, like logged-in user patient used for retrieving data from a patient record, assuming a given patient has been associated with the form entry session at the application level The data returned by the preloader is stored into the instance as the default value. Contact a developer for more details on how to use preloaders. Note: the custom preload parameters may be deprecated in the future, and replaced with a scheme that uses <setvalue> and custom XPath functions. Paths and Expressions ¶ XPath paths are used in XForms to reference instance nodes to store or retrieve data. JavaRosa currently supports both absolute and relative paths, along with using the proper relative path context node, depending on the situation. Paths can currently only reference XML elements (not attributes, comments, or raw text). Paths can currently only use the parent and child axes, and cannot have predicates. Basically, this means only paths of the form /, a-node, /path/to/a/node, and here/is/another/path are allowed. You may also use the shortcuts . and .. at any point in the path. Rules for the relative path context node are as follows: for xforms controls at the top level (not inside a <group> or <repeat>), and for nodesets in <bind>s, the context node is the top-level instance node (the immediate and only child of <instance>) for xforms controls inside a <repeat> or <group>, the context node is the binding node of the <group> or <repeat>. If inside a <group> that does not define a binding, use the next <group>/<repeat> up the hierarchy, until the top level is reached for expressions inside attributes in a <bind>, the context node is the node defined in the nodeset attribute of that <bind>. Controls and <repeat>s may use the ref and nodeset attributes, respectively, to define their binding. They may also use the bind attribute to refer directly to a given <bind> element via its id attribute. There is not much point to this convention, though, as it just adds one more step of indirection. You should favor using ref and nodeset. XPath expression are supersets of XPath paths. An XPath expression contains various XPath paths, along with comparisons, operators, and functions, to evaluate some condition. These conditions are used for the relevant, constraint, and more rarely, readonly and required attributes. When evaluating, any paths are replaced with the data value currently stored in the node referenced by the path. If a path does not uniquely identify a single node, but instead a set of several nodes (such as a node that may be <repeat>ed), the path will not evaluate to a data value, but instead evaluates to a nodeset. Consult the XPath 1.0 specification for details on XPath. The JavaRosa implementation of XPath is quite feature complete, and follows proper XPath semantics very closely. The only exception is the set of built-in XPath functions. JavaRosa only supports a limited subset of XPath functions, and adds some custom ones as well. JavaRosa XPath functions: Function Action true() returns true false() returns false boolean(x) converts x to a boolean value; conversion varies depending on data type of x number(x) converts x to a numeric value; conversion varies depending on data type of x string(x) converts x to a string value; conversion varies depending on data type of x date(x) converts x to a date value; conversion varies depending on data type of x not(x) negates boolean value x boolean-from-string(x) returns true if x is "true" or "1", false otherwise. note that this is different behavior than boolean(x) if(cond, a, b) evaluate cond; if true, return a, else, return b selected(multi-select, multi-select is the path to the answer of a multi-select question; return true if choice) choice is one of the selected answers count-selected(multi- multi-select is the path to the answer of a multi-select question; return the select) number of selected answers count(nodeset) count the number of nodes in nodeset sum(nodeset) return the sum of the values of the nodes in nodeset today() return today's date now() return a timestamp for this instant checklist(min, max, v1, v2, v3, ..., vn) v1 through vn are a set of n yes/no answers. return true if the count of 'yesses' is between min and max, inclusive. min or max may each be -1 to indicate 'not applicable'. this is how you do 'at least 3 of ...' and 'at most 4 of ...' -type conditions Additional functions may be added via custom Java function handlers that are registered at run-time. Many operations are only defined for a certain set of data types. XPath typically makes a good faith effort at converting your value to the proper data types, but make sure you understand the semantics of the type conversion, or you may get confusing results. Sometimes, it is not possible to convert your value to the desired type, and you will get a run-time error. For example, using a nodeset anywhere other than where a nodeset is explicitly expected will usually cause a type error. Groups and Repeats ¶ JavaRosa supports <group>s. Groups may have a label, a ref, both, or neither. If a <group> has a <label>, it is considered a presentation group, and visual hints will be presented to the user as they fill out the form that the questions within the group are related (such as placing all questions under a banner whose caption is taken from the <group>'s <label>). If a <group> contains a ref attribute, it is considered a logical group, meaning the answers for all the questions within the group are stored together ('grouped') in the instance (i.e., the <group>'s ref is the parent of the refs of all child questions in the <group>). To that end, the <group>'s ref is used as the context node for the relative ref paths of the group's child questions, allowing these refs to be abbreviated even further. (note: it is not strictly required that child questions of a logical group store their answers under the <group>'s ref in the instance (such questions may use an absolute path pointing elsewhere for their ref), but it is confusing to do so, so please don't). We also support the <repeat> tag, which allows repeating a question or set of questions an arbitrary number of times. The nodeset attribute of the <repeat> specifies the instance node to be parameterized -- that is, it is this exact node (and all its children) which is duplicated each time a new repetition is created. Our implementation of <repeat> is pretty standard, but it diverges in several ways. In pure xforms, 'create new repetition' and 'delete repetition' actions are initiated manually by the user, who does so using special <trigger> controls created explicitly for this purpose. JavaRosa provides these actions automatically as part of the form entry UI. For example, the user will be prompted when necessary if they want to create a new repetition, and when they are inside a <repeat>, the 'delete' option is available under a menu. These <trigger>s are unnecessary, and will be ignored if present. In xforms, data preloaded into your instance is treated as default values. However, for <repeat>able nodes, it is ambiguous whether to use the data as the default for just the one repetition, or as the default for all future repetitions. To resolve this, we added the jr:template attribute. Without this custom attribute, every repetition of a node will be considered valid data, and the default values within each node will be used as default values only for that repetition; the default values for all newly-created repetitions will be blank. Example: <instance> <data xmlns="..."> <name>Jimmy</name> <name /> <name>Julia</name> </data> </instance> <name> is a repeatable node. The form entry UI will treat this as having three repetitions already created. When going through the form, the user will see the question 'Name 1:' with a default of 'Jimmy', then 'Name 2:' with no default, then 'Name 3:' with a default of 'Julia'. After 'Name 3:', they will be asked 'Add another Name?'. If they do, the default for this new repeated name will be blank. Now lets add the jr:template attribute: <instance> <data xmlns="..."> <user jr:template=""> <region>BOSTON</region> <name /> </user> <user> <region>NEW YORK</region> <name>Jasper</name> </user> </data> </instance> Adding the jr:template attribute (value is irrelevant) to a repeatable node in the instance indicates that this repetition should be used as the default for all future repetitions that are created, and is not considered an actual repetition itself. In the above example, the form entry UI considers there to be one repetition already created (whose questions have default answers of NEW YORK and Jasper, respectively). Any newly-created repetitions will have a default region of BOSTON. The template is never included when submitting the instance. If the only <user> in the instance above was the template user, then there would be zero users by default, and we would prompt whether we even want to create a user in the first place. In short, you pretty much always want to add a template declaration for your repeatable nodes. A <repeat> is given the same visual hints in the UI as a <group>. Again, the caption used for the banner header is taken from the <repeat>'s <label>. To associate a <label> with a <repeat>, use the following syntax: <group> <label>[caption]</label> <repeat nodeset="..."> ... </repeat> </group> (this is standard xforms syntax, not a JavaRosa customization. the enclosing <group> must contain no other children) It is possible to specify that a repeat may not have interactive additions or removals through the use of the attribute noAddRemove. If this is set, the user will not be prompted to be able to add a new instance of a repeat in the user interface. This is helpful when use in conjunction with the next attribute, which allows you to specify a hint as to how many nodes should be available. Note that at the moment, the content of the attribute is unimportant (Any content in the attribute enables the property), but should probably be set as an xpath for now so that forms will be compatible in the future. You can specify a hint in the count attribute for the form entry session as to how many instances of a repeat should be available to the user without any interaction necessary. This will pull an integer value from the data model, and ensure that at least that many instances are available to the user when they fill out the form. When used with the noAddRemove attribute this give you a way to automatically handle repeats without any interaction. This might look like <group> <label>FOO</label> <repeat nodeset="..." jr:noAddRemove="true()" jr:count="/path/to/some/integer"> ... </repeat> </group> which would pull the integer inside of /path/to/some/integer and have the user create that many repetitions for FOO. If noAddRemove isn't set, after the repetitions are completed, the user will be asked if they want to add more. You can limit how many repetitions can be created through a constraint on the repeatable node (e.g., <bind nodeset="[same as the nodeset of the <repeat>]" constraint="count(.) <= 5" />). <group>s and <repeat>s may be nested within each other arbitrarily deep. Things we want to be able to do with <repeat>s but can't yet: 1. Use dynamic logic to specify whether a repeat can be added to, rather than a static flag Multi-lingual Support ¶ XForms provides no way to dynamically support multi-lingual content in a single form. We've devised our own way where all language-dependent strings are replaced with 'text identifiers', which act as indexes into a multi-lingual dictionary in the model. In the <model>, you can add a multi-lingual dictionary with the following structure: <itext> <translation lang="[language name]"> <text id="[text id]"> <value>[this language's translation of the string corresponding to [text id]]</value> </text> </translation> </itext> Additional <text> entries are added for each localizable string. The <translation> block is duplicated for each supported language. The content should be the same (same set of text ids) but with all strings translated to the new language. The language name in the lang attribute should be human-readable, as it is used to identify the language in the UI. A default="" attribute can be added to a <translation> to make it the default language, otherwise the first listed is used as the default. Every place localized content is used (all <label>s and <hint>s) must use a converted notation to reference the dictionary: <label>How old are you?</label> is changed to <label ref="jr:itext('how-old')" />. With the corresponding entries in <itext>: <translation lang="English"> ... <text id="how-old"> <value>How old are you?</value> </text> ... </translation> <translation lang="Spanish"> ... <text id="how-old"> <value>¿Cuantos años tienes?</value> </text> ... </translation> ... Not every string must be localized. It is acceptable to intermix <label>s of both forms. Those which do not reference the dictionary will always show the same content, regardless of language. In general, all text ids must be replicated across all languages. It is sometimes only a parser warning if you do not, but it will likely lead to headaches. Even within a single language, it is helpful to have multiple 'forms' of the same string. For example, a verbose phrasing used as the caption when answering a question, but a short, terse phrasing when that question is shown in the form summary. We handle this as follows: <text id="how-old"> <value form="long">How old are you?</value> <value form="short">Age</value> </text> This is only supported for question captions (<label>s inside user controls). XForms Roadmap ¶ The following features are on the roadmap to be added to the JavaRosa xforms engine: support for more data types for <input>, including date with time (dateTime), time (time), year (gYear), month (gMonth), year with month (gYearMonth), month with day (gMonthDay), email, etc. support for <secret>, <range>, and <textarea> controls full-featured and multi-lingual support for <output> full-featured and intuitive support for <upload> (data capture, like camera, audio recording, etc.) native support for data types like GPS and RFID, where device capabilities permit support for the appearance attribute to control look-and-feel support for dynamic list selections through the <itemset> attribute support for evaluating xpath predicates (immediate use case: helping support better dynamic list selections) support for multiple instances and models (immediate use cases: provide reference data for dynamic list selections; provide a place to store interstitial variables you don't want submitted) support for 'open' list selections, meaning you can type in an 'other' value not on the list support for grouping questions into a single control (e.g., weight + unit (lbs/kgs)) allow binding controls to instance node attributes support multi-lingual constraint messages support multiple constraints on the same node (with unique messages) support different severities of constraints, such as hard constraint (always rejected), soft constraint (warning only), and medium constraint (warning, but only accepted after some kind of override process (e.g., type your initials, enter your password...)) support calculate attribute support <setvalue>, replace jr:preload support <hint>, <help>, and <alert> support pre-populatation (explicit or tied to another question) and add/delete restriction for <repeat> This does not imply any delivery date, however, or that any development resources have been allocated. This is simply a list of features we'd like to be able to support, some more strongly than others.
"XForms Training Materials"