XRX/Selection List Generator
Motivation
editYou want to store all your code tables in a central location and have each form dynamically generate selection lists from these code tables.
Method
editWe will create a very simple XML file format to store all our codes. We will store one code table per file and then write a simple XQuery that goes through all these files to build a sample selection list. This selection list will create an instance in the model to hold each selection list value. It will also populate the instance with the first value in the list.
In our sample, we will assume an XRX file naming standard such as /db/apps/app-name/code-tables/my-code-table.xml where each application contains its own code tables for maximum application portability between systems. Applications that share code tables can store these in a location such as /db/shared/code-tables/my-code-table.xml
Sample Screen Image
editXML File Format
edit<code-table>
<code-table-name>PublishStatusCode</code-table-name>
<definition>A way to classify the publishing workflow of an item.</definition>
<items>
<item>
<label>Draft</label>
<value>draft</value>
</item>
<item>
<label>Under Review</label>
<value>under-review</value>
</item>
<item>
<label>Published</label>
<value>published</value>
</item>
</items>
</code-table>
Sample XQuery
editThis query goes through all the files in the XRX application code-tables collection and looks for XML files that have code-table as the root element. It then creates a report that contains all the selection lists inside a working XForms application.
xquery version "1.0";
import module namespace style ='http://code.google.com/p/xrx/style' at '/db/xrx/modules/style.xqm';
declare namespace xhtml="http://www.w3.org/1999/xhtml";
(: XQuery to construct an XForm for either a new item or update item :)
declare option exist:serialize "method=xhtml media-type=application/xhtml+xml indent=yes";
let $app-collection := style:app-base-uri()
let $code-table-collection := concat($app-collection, '/code-tables')
let $code-tables := collection($code-table-collection)/code-table
return
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events">
<head>
<title>XForms Selection List Tester</title>
{style:import-css()}
<link type="text/css" rel="stylesheet" href="block-form.css"/>
<xf:model>
<!-- This instance holds the value of each code -->
<xf:instance xmlns="" id="save-data" src="">
<data>
{for $code-table in $code-tables
return
element {$code-table/code-table-name/text()} {$code-table/items/item[1]/value/text()}}
</data>
</xf:instance>
</xf:model>
</head>
<body>
{style:header()}
{style:breadcrumb()}
<h1>Sample with a Model in the XForm</h1>
{for $code-table in $code-tables
let $code-table-name := $code-table/*:code-table-name/text()
return
<xf:select1 ref="{$code-table-name}">
<xf:label>{$code-table-name}: </xf:label>
{for $item in $code-table/*:items/*:item
return
<xf:item>
<xf:label>{$item/*:label/text()}</xf:label>
<xf:value>{$item/*:value/text()}</xf:value>
</xf:item>}
<xf:hint>{$code-table/*:definition/text()}</xf:hint>
</xf:select1>
}
{style:footer()}
</body>
</html>
Note that this XQuery uses element constructors to create element names in the instance. It also uses the *:name notation to put data from the null namespace directly into the XForms namespace.
This file also puts the definition of the element directly into the hits of the XForms application. Under some XForms applications such as Firefox the hint appears in a floating ephemeral mode display in the left margin of the form.
Sample CSS File
editHere is the block-form.css file that can be used to make each selection appear on a separate line:
@namespace xf url("http://www.w3.org/2002/xforms");
body {font-family: Arial, Helvetica; sans-serif;}
/* This line ensures all the separate input controls appear on their own lines */
xf|output, xf|input, xf|select, xf|select1, xf|textarea {display:block; margin:5px 0;}
/* Makes the labels right aligned in a column that floats to the left of the input controls. */
xf|select > xf|label,
xf|select1 > xf|label
{text-align:right; padding-right:10px; width:250px; float:left;}