After spending some time, recently, showing you how to connect your form to a schema and highlighting Designer’s support for schema metadata, I thought I would round-off my current train of thought on schemas by tackling multi-selection listboxes. Since they store their selected data in <value> nodes, once you think about it, their schema definition may not be obvious. When you’re working with XML data that isn’t governed by a schema and namespaces, it is perhaps easier to work with (i.e. accept) these <value> nodes however things change when you have a schema telling you how your data must be structured and scoped (with namespaces).
How Lists Store Selected Items
To better understand the challenges, let’s look at how list form objects store a multi-selection of values.
In the Form DOM, the list’s value actually contains XML rather than plain text. For example, say we have a multi-selection list named “ListBox1″ (bound to a data element named “list1″) with items (“item1″, “item2″, “item3″). If the first two items were selected, the list’s value would look like this:
<value> <exData contentType="text/xml"> <list1> <value>item1</value> <value>item2</value> </list1> </exData> </value>
In script, this would translate to a newline (\n)-delimited string when the list’s value is accessed from its rawValue property:
In the Data DOM, the list’s value is stored in a series of repeating <value> nodes, much like the way it is stored in the Form DOM:
<list1> <value>item1</value> <value>item2</value> </list1>
Adding the Schema
A schema describes how XML should be structured. Given how lists store their selected items in data, a schema that includes a multi-selection list will need to allow for the element that defines the list to contain zero or more repeating <value> nodes. Unfortunately, this means modifying your schema, if you already have one. (I can think of at least one workaround to this which would involve script and a sibling, hidden text field bound to the element in your schema, as opposed to the list itself, in which you would store the selection, but I won’t get into that in this article.)
For example, this is a schema that defines a “form1″ root element that contains an element named “list1″ that has a multi-selection list type (the way XFA expects it).
The problem with this structure is that once you connect your form to this schema, the Data View connection tree will interpret the list1 element as being a subform that contains a repeating node, “value”:
Because of this interpretation, you cannot simply drag & drop the “list1″ schema element into your form in order to get a multi-selection list. Instead, you’ll get a subform with a text field inside of it instead (only an element with a simple type restricted to an enumeration of values would be interpreted as a list). Furthermore, you cannot use the picker widget next to the “Object palette > Binding tab > Data Binding property” to assign “list1″ to a listbox you have already dragged into your form from the Object Library palette because “list1″ is viewed as a container (subform) and the form object you are attempting to bind is a field.
In order to bind the listbox to the “list1″ schema element, you must manually type its binding expression into the “Object palette > Binding tab > Data Binding property”. For our simple use case, the binding is “list1″. Note that you don’t actually bind the repeating “value” element to anything and that the schema data connection tree will not actually indicate that the “list1″ element is bound to a form object even though it now is (I’m guessing this is because it is expecting “list1″ to be bound to a subform, not a field).
The result of binding the listbox to the “list1″ schema element is that the Form DOM output changes slightly to include the proper namespace on the bound element within the field’s value:
<value> <exData contentType="text/xml"> <scof:list1 xmlns:scof="http://forms.stefcameron.com/ns/2009/"> <value>item1</value> <value>item2</value> </scof:list1> </exData> </value>
As you might expect, given the structure of the listbox’s selection in the Form DOM above, the list’s selection data will be similar in the Data DOM (which is what would be submitted from the form as well):
<xfa:data xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/"> <scof:form1 xmlns:scof="http://forms.stefcameron.com/ns/2009/"> <scof:list1> <value>item1</value> <value>item2</value> </scof:list1> </scof:form1> </xfa:data>
The only problem with the data above is that it isn’t valid against the schema which specifies that the repeating <value> nodes inside the list1 element are part of the “scof” (target) namespace and should therefore look like <scof:value>.
Submitting Namespaced Data
In order to get the namespace into the repeating <value> nodes for the selected values, we have to use a workaround that involves a little script in the listbox’s Exit event (though the script could be triggered elsewhere, if you like):
The script above essentially builds an XML string equivalent in structure to that which is normally used to store the list’s selection in the Form DOM however it adds the necessary namespaces to the repeating <ns:value> nodes. This change is then replicated in the list1 data node in the Data DOM and the form’s exported data changes to this (which can be successfully validated against the schema we’re using):
<xfa:data xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/"> <scof:form1 xmlns:scof="http://forms.stefcameron.com/ns/2009/"> <scof:list1> <scof:value>item1</scof:value> <scof:value>item2</scof:value> </scof:list1> </scof:form1> </xfa:data>
Unfortunately, I have to point-out a bug as it relates to exporting multi-selection values with namespaces (which you only get when you use the above workaround script): Importing data with namespaced <ns:value> nodes for multi-selection lists — though valid XML and valid against the schema — will fail in Acrobat 9.1.3 (I have not done any testing on previous versions). My testing has revealed that the form doesn’t render properly after the data merge. Importing namespaced data that does not have namespaced <value> nodes for multi-selection lists, however, does work fine (this is the default way data is exported, unless you use the script I outlined above).
I have built a sample form that demonstrates how multi-selection lists store their data in the Form DOM and Data DOM. The form also includes a checkbox which, when checked, will generate namespaced <ns:value> nodes instead of the default <value> nodes, using the workaround script in the list’s Exit event.
Minimum Requirements: I designed this form using Designer ES2 Beta and Acrobat 9.1.3 however the form should work all the way back to Designer 7.1 and Acrobat 7.0.5.
Posted by Stefan Cameron on September 30th, 2009
Filed under Acrobat,Bugs,Data Binding,Scripting,Tutorials,XFA
Both comments and pings are currently closed.