XRX Toolkit
From Open Siddur Project Development Wiki
XRX (XForms-REST-XQuery) is an web application architecture where XForms is used to provide the user interface (fulfilling much of the role of Javascript and Javascript libraries), XQuery provides the server-side processing (fulfilling the usual role of PHP), and REST requests to a server (typically an XML database) glue the XForms to the data on the server (roughly equivalent to AJAX calls).
In the XRX architecture, data is stored as XML both on the client and server. While some data format shifting is needed, far less is required than when shifting between Javascript's native structures and XML.
The Open Siddur XRX toolkit is a set of categorized XQuery function modules for server-side generation of XForms and data processing. In order to develop with it:
- familiarize yourself with the basics of XQuery and XForms.
- For XForms basics, the online tutorial at W3Schools provides a good introduction; Micah Dubinko's XForms Essentials is also a good resource. The XForms wikibook provides an introduction and a number of examples.
- install a mirror of the database on your local machine.
Contents |
A First app
Applications are stored inside the database in their own collection in /db/code/apps/. This application, for example, may be stored as helloworld.xql in the database collection /db/code/apps/helloworld.
To get the application into the database, start up the database and place the application in your working copy in code/apps/helloworld (note: all working copy paths are relative to the tag you're using, eg: trunk, branches/efraim). Run:
make db-svnsync
which will sync the database to the contents of your working copy.
The conventional "Hello World" application:
xquery version "1.0"; (: Hello world application :) (: import the site module from /code/modules/site.xqm :) import module namespace site="http://jewishliturgy.org/modules/site" at "../../modules/site.xqm"; (: declare html namespace and tell eXist to output XHTML :) declare namespace html="http://www.w3.org/1999/xhtml"; declare option exist:serialize "method=xhtml media-type=text/xml"; (: call site(model, head, content). : we have no model :) site:form( (), <html:title>Hello world application</html:title>, <html:div> <html:p> Hello, world! </html:p> </html:div> )
The application above will simply display "Hello, world!" using the Open Siddur applications' header and footer. It will run when you point your browser to
http://localhost:8080/code/apps/helloworld/helloworld.xql
while the database is running.
Modules and apps
The XRX toolkit is separated into modules and apps. XQuery Modules (.xqm extension) provide function libraries that can be used by applications to do work. These functions both operate on data and provide standard interfaces and UI controls. Each module is uniquely identified by a URI namespace (such "http://jewishliturgy.org/modules/site"). When loading a module (with import module namespace ...), both the namespace and the location of the module (at "...") must be referenced. When you call functions in the module, the function names are prefixed by the module's namespace prefix (as in site:form).
Apps group together function modules and user-executable interfaces that operate on related data. For example, the "contributors" app operates on the contributor list, and the "bibliography" app operates on bibliographic records.
Example: Adding a login control
The login control is provided by a module in the user management application (/code/apps/user).
In XForms, structured data is declared in "instances" in the data model, and user interface code references those instances. The content of the instances is submitted to the server through HTTP, and the server places the result in another instance. In the Open Siddur XRX toolkit, modules provide *-instance() and *-ui() functions that place the instances and user interfaces of the common controls in the appropriate places.***
Modifying our "Hello world" application, we get:
xquery version "1.0";
(: Login control example application :)
(: import the site module and the login module :)
import module namespace site="http://jewishliturgy.org/modules/site"
at "../../modules/site.xqm";
import module namespace login="http://jewishliturgy.org/apps/user/login"
at "../user/modules/login.xqm";
(: declare html *and* xforms namespaces :)
declare namespace html="http://www.w3.org/1999/xhtml";
declare namespace xf="http://www.w3.org/2002/xforms";
declare option exist:serialize "method=xhtml media-type=text/xml";
(: call site(model, head, content).
:)
site:form(
<xf:model>{
login:login-instance('login')
}</xf:model>,
<html:title>Login control example application</html:title>,
<html:div>
<html:h1>Login example application</html:h1>
{login:login-ui('login', 'control-login')}
</html:div>
)
App structure
Apps have a general directory structure template:
controller.xql app-info.xml search/ search.xql views/ view-item.xql list-items.xql edit/ edit-item.xql edit.xql new-instance.xml delete.xql save.xql update.xql modules/ controls.xqm common.xqm scripts/ *.xsl2 styles/ *.css
Catching and displaying error messages
Form validation errors
To do server-side validation of the data in a control, add a call to the following XQuery function in the instance
controls:validator-instance( $control-id as xs:string, $instance-ref as xs:string, $validator-url as xs:anyURI, $event-target as xs:string? (: optional :) )
and add a call to the following function as a child of the control:
controls:validate-action( $control-id as xs:string, $instance-ref as xs:string, $incremental as xs:boolean )
If you give controls:validator-instance() a $event-target parameter, you may also catch the events:
- validator-ok
- validator-warn
- validator-error
- xforms-submit-error
The $validator-url parameter points to an XQuery that will run whenever the control data needs to be validated. The data will be sent as XML via POST. An optional lang= query parameter may be sent, indicating the preferred language for error messages.
The XQuery validator must return one of:
- A single <ok/> element, indicating that the input data is valid
- A single <warn type="">text</warn> element, indicating that the input data is valid, but there may be a problem with it. The optional type is a computer-parsable code indicating the warning type.
- A single <error type="">text</warn> element, indicating that the input data is invalid. The type is a computer-parsable code.