Handling data

last update: 30. March 2012

In the old days of HTML forms there were only limited possibilities to load and submit data. They could be hard-coded into the page as values of controls and sent as a http request to a server with GET and POST.

XForms on the other hand has a rich set of features to load data from arbitrary sources, use different protocols, methods and encodings, provide response handling etc. etc.

This section will touch the basics of loading and saving of data and introduce some betterFORM extensions in this area.

Inline data

The simplest way to work with some XML data is to write them inline within your form markup:

<xf:model>
       <xf:instance id=“myInstance“>
           <data xmlns=““>
               <address>
                   <city>Berlin</city>
                   <street>Hohenzollerndamm</street>
                   ....

When your form comes up and has controls binding to the above data they will display ‘Berlin’ and ‘Hohenzollerndamm’. Instances can be used to preset some data before showing the rendered form.

Be aware of one important concept of XForms: once the instance is loaded a separate document will be created for it which clones the inline data. All data manipulations are happening on this external document. You’ll never see the inline instance change at runtime. This is true for all instances independent of how they were loaded.

The baseURI

One important concept for the resolution of data is the baseURI. Every XHTML/XForms document will have a baseURI. This is the place from where the document was loaded into the XForms processor. If the document happens to be on a server in the internet (which will be most often the case), the baseURI will be an absolute http URL pointing to the document itself. If your processor is capable of loading XForms from the file system it will be a file:/ URL.

In many web-apps documents are created dynamically by a template language. In this case they don’t really exist under a certain URL (instead they will have the URL of the templating engine) and it may be necessary to assign an explicit baseURI. This can be done with the xml:base attribute.

Example:

<xhtml:html xml:base=“http://anotherHost/foo“ ...

Loading data

The simplest way to load some data into a form is the use of the src and resource attributes of Element instance. Here’s an example:

<xf:instance src=“data.xml“>      ...

Once the XForms processor initializes the instances the src Attribute will be evaluated, the link will be resolved and the resulting response will be parsed as XML. If something fails a xforms-link-exception is dispatched.

Loading data this way is rather limited as there’s no way to customize the request. It will be a plain GET request to fetch the referenced resource. There is no way to send parameters, headers or use a different request method.

This will be fine as long as you have plain, more or less static resources such as language files, static reference lists or helper instances. If you have more fine-grained requirements you should use the XForms submission module which gives you all to interact with complex webservices, do authentication, handle exceptions or other events and give messages to the user. The full feature-set is too rich to be explained here in detail but some simple examples should get you started.

Loading data with submission

<xf:instance id=“myData“>
      <data xmlns=““>
          <foo/>
      </data>
 </xf:instance>
 <xf:submission
      id=“mySubmit“
      method=“GET“
     replace=“instance“
     resource=“http://myHost/myTarget“ ...>
     <xf:action ev:event=“xforms-submit“>
          <xf:message level=“ephemeral“>
              about to send your data...
          </xf:message>
     </xf:action>
     <xf:action ev:event=“xforms-submit-done“>
          <xf:message>success!</xf:message>
      </xf:action>
      <xf:action ev:event=“xforms-submit-error“>
          <xf:message>oops, an error occurred</xf:message>
      </xf:action>
 </xf:submission>

The above examples shows the loading of data by using a submission with method GET to load the wanted data from ‘http://myHost/myTarget‘. The response will be parsed as XML and used as instance data. This is expressed by the replace Attribute with value ‘instance’.

A XForms processor will send specific events at the different stages of submission. First a xforms-submit will be dispatched before the submission actually starts. Dependent of the success or failure of the request the event xforms-submit-done or xforms-submit-error will follow. These events can be used to inform the user, deal with exceptional cases or show details about the problem.

When data have to be loaded at startup it’s common to attach the send action to a xforms-ready event to fire the submission „mySubmit“ automatically once everything is initialized.

<xf:model>
 ...
 <xf:action ev:event=“xforms-ready“
 <xf:send submission=“mySubmit“/>
 </xf:action>
 ...
 </xf:model>

Hint:
Although this example focusses on the loading aspect all XForms submissions also send data even for method GET. In this case the existing instance data will be send urlencoded on the GET string. If you want to suppress that and send a plain GET use serialization=“none“ on your submission element.

Sending data

Sending of data works the same as in the example above. Besides using GET you can use POST, PUT and DELETE and have a rich set of switches to tailor your request, define the target and the handling of the response. Please refer to Chapter 11 of the XForms 1.1 Final Recommendation for a full overview of the Attributes and child Elements.

Using parameters

In the early days of XForms all submission action targets and instance src Attributes were only static strings. But of course this limited their usefulness a lot. In almost any application you need a way to pass params on the request string. This was hard in these days and the implementers had to make inventions.

One natural fit for use in XForms is the adaption of the so-called Attribute Value Templates (AVT) from XSLT. For any attribute the contents between curly brackets is interpreted and evaluated as a XPath expression.

betterFORM supports the AVT approach in very limited areas as on submission resource or action Attributes, on the instance src Attribute and for load resource Attribute. An enhancement of the support is planned for future versions.

As part of an AVT a variable expression or XPath expression can be used. Variables start with a ‘$’ followed by the name of the variable. An expression not starting with a ‘$’ is interpreted and evaluated as an XPath.

This table shows the support for Variables and XPath expressions for different Elements:

AVT support Variable XPath
Instance src Yes No
Submission resource (action) Yes Yes
Load resource Yes Yes

Using variables

As mentioned variables always start with a ‘$’ sign. There are several predefined variables, some HTTP header-related ones as well as a variable for every param your document was called with. An example will illustrate this.

Assume your document was called with the URL:

http://myhost.com/mydoc.xhtml?filename=foo.xml&bar=baz

betterFORM will parse all params and store them. You may then access the values of these variables:

<xf:instance src=“{$filename}?query={$bar}“>     ...

Variables can be accessed in two ways:

  • starting with a ‘$’ sign as prefix in AVTs on the above mentioned XForms Elements
<xf:submission resource=“http://myHost/{$foo} ...
  • by using the appContext() XPath function. This will take a variable name as string argument and return the respective value. This function can be used anywhere in XForms where a XPath expression is allowed.
<!-- this output will display the webapp context string --> <html xmlns:bf="java:de.betterform.xml.xforms.xpath.BetterFormXPathFunctions">     ...     <xf:output value=“bf:appContext('contextroot')“ />     ...

Available Variables

The available variable can be seen on the ‘Status.xhtml’ form which comes with betterFORM.

betterform.baseURI The absolute baseURI of the document.
contextroot Returns the web-app context name e.g. ‘/betterform’.
betterform.locale A lowercase two-letter ISO-639 language code denoting the selected locale.
httpSessionId Returns the HTTP sessionId for the current user.

Please note that the name of this param is dependent on the web container implementation. ‘httpSessionId’ is the key that is used by Tomcat.

queryString The query string passed on current URL.
requestURI Absolute HTTP URL for the current web-app e.g. http://myHost/betterform
requestURL The absolute HTTP URL of the form. This will have the same value as $baseURI unless the baseURI has not been modified by the xml:base Attribute.
webapp.realpath The absolute file URL of the webapp context.
Any URL param Besides the whole querystring as available from the ‘queryString’ variable each param passed to the form will be present as standalone variable. E.g. if a ?foo=bar param is passed you can access the variable $foo or bf:appContext(‘foo’) to get the value ‘bar’.
HTTP-headers Any HTTP header will be stored as a variable. To e.g. access the user-agent use the key ‘http-headers/user-agent’. It depends on the environment which headers will be sent by a given browser. Most of the time following keys should be present:- http-headers/host- http-headers/user-agent

– http-headers/accept

– http-headers/accept-encoding

– http-headers/accept-language

– http-headers/accept-encoding

– http-headers/accept-charset

– http-headers/keep-alive

– http-headers/cookie

Other headers may be present but you shouldn’t rely on them unless you’re sure they are sent.

Using XPathes in AVTs

Especially if you want to route your requests dynamically dependent on some data in your instance(s) it is necessary to use XPathes in your submissions or load actions.

Example:

<xf:instance>      
    <data xmlns=““>
           <newURL>http://www.google.com</newURL>
       </data>
</xf:instance>
<xf:submission resource=“{instance()/newURL}“ ...

In this example the AVT inside of the submission resource Attribute will be evaluated before the submission actually takes place thereby leading to a changed location depending on the value currently set in the instance.

Noteworthy helpers

This section lists some helpful Connectors you can use in your forms. Please be aware that some of these are extensions that are not found in other implementations.

Ant

This submission handler allows to execute Apache Ant target from within an XForms document.

[tbd]

Context

(betterFORM  extension)

This submission handler allows to store an instance within a global hashmap inside of the XForms processor. It is useful to pass instances between models (see article ‘model to model communication’) or subforms.

See Model to Model Communication for an example.

Echo

(betterFORM extension)

As the name says: The EchoSubmissionHandler just echoes the XML back that was sent to it. This may be useful for debugging.

This SubmissionHandler is by config registered to the URI scheme ‘echo:’. As a full URI must have a non scheme-specific part you have to put an arbitrary string behind the echo though it’s not processed in any way:

<xf:submission resource=“echo:void“ .. />

Exec

(tbd)

File

File is a standard protocol available in XForms. betterFORM extends the functionality by providing a directory listing. When the file you are referring to is a directory a directoy listing for that directory will be created in XML. This comes in hand when you need to browse a server-side filesystem.

The directory listing capability is present in the FileURIResolver and the FileSubmissionHandler meaning you can use it in instance src and submission resource.

Please be aware of the security concerns that might arise from using this. Be cautious to allow browsing since the user might step through your whole filesystem.

SMTP

The SMTP submission driver serializes and submits instance data over SMTP (internet mail).

Currently, the driver only supports the post submission method and the replacemode none. The driver requires the additional information about the SMTP

server to use, the mail subject, and the sender. This information has to be passed in the query part of the submission’s action URI. If you want the driver to authenticate a user with the SMTP server, just provide a username and a password.

Be careful when writing the submission’s action URI: First, the contents of the query part has to be URL-encoded, then you have to replace all &amp;’s with their corresponding XML entity &amp;amp; in order to keep the XML well-formed.

Example:

<xf:submission id='smtp'
       resource=“mailto:nn@nowhere.no?server=smtp.nowhere.no&amp;amp;sender=xforms@nowhere.no&amp;amp;subject=instance%20data“

Another example with authentication:

<xf:submission id='smtp-auth'
      resource=“mailto:nn@nowhere.no?server=smtp.nowhere.no&amp;amp;sender=xforms@nowhere.no&amp;amp;subject=instance %20data&amp;amp;username=xforms&amp;amp;password=shhh“

Support for other mail header fields like cc may be added later.

XMLRPC

(betterFORM extension)

You can connect to XMLRPC servers by using XMLRPCURIResolver and XMLRPCSubmissionHandler. These are both configured with URI scheme ‘xmlrpc:’.

The XMLRPCURIResolver resolves xmlrpc URIs. It treats the denoted xmlrpc resource as a XML-RPC function, with parameters passed as a query string to the URI. The URIs look like this:

xmlrpc://server:port/path/[xmlrpcQuery]?[xmlrpcParameters]#frag

The function is called with the parameters in a hash table, and an XML Document is returned.

If the specified URI contains a fragment part, the specified element is looked up via getElementById. Thus, the parsed response must have an internal DTD subset specifying all ID attribute. Otherwise the element will not be found.

The XMLRPCSubmissionHandler parses the string given by the resource Attribute, extracts function and parameters from it and executes the remote function.

XSLT

(betterFORM extension)

The XSLTSubmissionHandler applies an XSLT transformation to the submitted instance and is useful when you want to apply some sorting or filtering of the instances.

For a base URI of e.g. file:///Users/JohnDoe/Forms/bin the submission URI xslt:../xsl/my.xslt?foo=bar will result in the following processing steps:

  • After URI resolution the XSLT stylesheet is loaded from
  • file:///Users/JohnDoe/Forms/xsl/my.xslt.
  • A Transformer is created for that stylesheet and the uri param foo=bar is passed to the stylesheet as xsl:param ‘foo’and its value‘bar’.
  • The submitted instance is transformed using that Transformer.
  • The transformation result is returned as a stream in the submission response.

3 Comments Add your own

  • 1. Stefan Krause (@Stf_)  |  November 26, 2011 at 6:05 pm

    It seems that there was a change regarding variables. Using bffn: namespace declaration and bffn:appContext() causes an exception, but using bf:appContext() without namespace declaration (as in Status.xhtml) works fine. I use betterFORM limeGreen RC 4. Could you please look into it?

    Reply
    • 2. joernturner  |  November 29, 2011 at 9:36 am

      simply use bf namespace now instead of bffn

      Reply
    • 3. joernturner  |  November 29, 2011 at 9:43 am

      document is updated now.

      Reply

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Trackback this post  |  Subscribe to the comments via RSS Feed


%d bloggers like this: