XForms, a pause for reflection

By Philip Fennell
December 17, 2008 | Comments: 4

The other day I had what could only be described as a 'Roy Scheider moment'. You know the bit in the film Jaws where, as Police Chief Brody, he's sitting on the beach and just when he becomes aware of people shouting 'Shark' the camera tracks-in whilst zooming-out at the same time. It's a great effect that gives you an impression of that moment when surprise and a greater awareness converge.

Well, whilst debugging an XForms enabled application (quite mundane by comparison) with a combination of the Mozilla XForms, XForms Buddy and Firebug plug-ins I noticed something rather unusual. GET requests against an empty xf:instance were generating URIs with many parameters, which is rather odd when you consider the actual request URI specified for the xf:submission element had no parameters at all. I could see the submitted URI from the Net tab in Firebug. The URI looked, for all the world, just like an application/x-www-form-urlencoded submission should do, except the GET request was made, as previously stated, against an empty xf:instance. However, there had to be something in the instance data for the serialization to have generated the parameters!

<xf:model xmlns:xf="http://www.w3.org/2002/xforms">
  ...
  <xf:submission id="retrieveService"
      mediatype="application/xml" 
      encoding="UTF-8"
      method="get" 
      replace="instance"
      instance="service">
    <xf:resource value="'http://localhost:8888/app'"/>
    <xf:header>
      <xf:name>Accept</xf:name>
      <xf:value>application/atomsvc+xml</xf:value>
    </xf:header>
  </xf:submission>
  <xf:instance id="service"/>
  ...
</xf:model>

The truth was revealed when I opened-up XForms Buddy and viewed the instance data in question. The Mozilla XForms plug-in had exposed the host document, XForms and all, as the content of the empty xf:instance. How odd. I mean, what good is that? That's when it struck me, in a Roy Scheider sort of way, this was Reflection, the ability of a program to look at itself and change its behaviour.

You can set-up data bindings to the host document that enable you to access information that would otherwise be unavailable to XForms. One example might be that you have generic form components that are included, server-side, into the application but require context information. You could have applied server-side transforms to contextualize the forms or alternatively, you could keep the XForms untouched and use Reflection to access the context information from the host document.

This is, on the face of it, just like XSLT's ability to access the current style sheet by calling the document('') function with an empty string as its argument. There is an article that covers XSLT Reflection by Jirka Kosek. However, unlike XSLT, this behaviour in XForms is not part of the W3C XForms 1.0 recommendation, or for that matter the forth-coming recomendation for XForms 1.1. I've not been able to recreate this behaviour on other XForms implementations (I've not tried them all yet), but that's not surprising really when you consider it is a non-standard feature. As a means of accessing the host document, it is not ideal either. If it were to become a feature of XForms, then access to the host document should be via a specific function call.

All that said, I must admit I did get rather excited at the prospect of reflective programming with XForms but there is more work to be done before that becomes a reality.


You might also be interested in:

4 Comments

Philip,

I love that camera effect, too. Another cool use of it can be found in Spike Lee's "Inside Man".

Anyway, I do believe you may have found a subtle and fascinating bug in the Mozilla XForms Extension (and possibly in the spec)! I'm quite looking forward to playing with this. I wonder if you can modify the host document DOM using this "back door". Obviously, you can already modify the host DOM using JavaScript, but this may not yet work flawlessly. So we have <xf:instance id="service"/>, which you could interpret as having an empty href attribute, which would be a same-document URI reference and thus resolve to the (host) document itself! Bug, or feature? I don't know; I'll investigate a bit further. Either way, your discovery is amusing.

@John,
> I wonder if you can modify the host document DOM using this "back door"
I should have mentioned this in the entry, but that was one of the first things I tried and, alas no, it would seem not. Again, just like XSLT, the document that you get access to is just static. You'd need the ability to re-evaluate the document but that could get horribly recursive.

Currently you cannot bind an xf:output to complex content. The only way to evaluate a tree fragment for re-rendering is to serialize it as text and pop it into another instance, then bind that text node to an xf:output with a mediatype of text/html. That way you can dynamically build rich and interactive content views that utilise embedded XForms controls and XML Events. This requires adding JavaScript and client-side XSLT into the mix but it can allow you to build very powerful and rich web apps.

It's difficult to know quite where to take all of this. I'd like to see the next version of XForms including an xf:transform (XSLT) action and the ability to bind to complex content. If we had access to the host document too then that'd be the icing on the cake.

@Philip

>I'd like to see the next version of XForms including
>an xf:transform (XSLT) action and the ability to bind
>to complex content.

It's a wonderful idea (I'm already using something similar on server-side (http://sourceforge.net/projects/txs)) and it could be an extension in XSLTForms (http://www.agencexml.com/xsltforms/).

Could you send me the kind of syntax it could have ?

@Alain,

> Could you send me the kind of syntax it could have ?

I've not sat down and given any really serious thought but off the top of my head I can imagine the following:

1) You'd want to identify which instance and which part of an instance you wished to transform, a bit like the xf:submission element's ref attribute. This would identify the source document[ fragment] for the transform.

2) You need to specify a URI that points to the XSLT transform that you wish to apply to the source in (1). Again, the xf:submission and/or xf:instance are good examples. You may wish to declare the URI explicitly through a resource attribute are you may want to derive the URI from instance data, and will therefore want an xf:resource element that can get the value for the URI from an XPath expression.

3) You have identified the XSLT you wish to use via URI, but is there a case for inline XSLT? You could set-up a separate model and have an instance that contains an XSLT transform that you can reference from the xf:transform action in some way, shape or form.

4) Parameters to the transform are another issue and they could be dealt with in the same way as the HTTP headers in xf:submission use the xf:header. An xf:parameter element that has name and value elements as its children, and the value element can have a static value or use an XPath expressions to generate its value.

5) Finally, we need a target for the result of the transform, and this is where it gets more complicated.

a) You may want to use an XSLT transform to apply a complex change to the instance data and therefore want the whole instance updated.

b) You may want to do the same as (a) but to only a fragment of the instance document.

c) You may want to send the result to a different instance, say if you were generating a 'view' of the instance data. In this example you'd need the xf:output binding to complex content as I described in my earlier comment.

On the face of it it all seems do-able but I'd imagine that the Devil is in the detail as always.

News Topics

Recommended for You

Got a Question?