The XForms Transform Function Module

From W3C XForms Group Wiki (Public)

__NUMBEREDHEADINGS__



Document title:
The XForms Transform Function Module
Editors
Nick Van den Bleeken, Inventive Designers
Abstract

This document, developed by the Forms Working Group, specifies the transform function which is a module for XForms 1.2 and allows the transformation of an XML sub-tree.

Status of this Document
This is a live wiki document. Although it often reflects the best understanding of the editors and members of the Working Group, it may be inaccurate and has not necessarily been reviewed. If you need a stable copy, use the most recent official version: http://www.w3.org/TR/xformstransformfunction.


Copyright © 2010 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.

Overview

The transform function allows you to do a transformation on an XML sub-tree. Depending on the XForms implementation different transformation languages can be supported. An example of a transformation language is XSLT.

The transform() Function

Object transform(string, node?)

This functions returns the result of the transformation of the provided XML sub-tree. The returned result can be either a node or a string depending on the result of the transformation. In the case of an XSL transformation the result is a node if the XSL output method is XML (or XHTML), in all other cases the result is a string. In the case of a node the node, and all of its descendants, will behave like they have a readonly model item property with value true() attached to them. The read-onlyness of the returned result can't be removed. The returned result will behave like an implicitly created instance with the root node having a readonly model item property set to true(), additionally there will be no way to remove the read-onlyness, not even with an explicit override using a bind element.

The first argument is the URI to the definition of the transformation (in the case of an XSL transformation it is the URI to an XSLT stylesheet). The optional second argument is the node that should be used as input for the transformation, when the second parameter is omitted the current context node will be used as input.

When the uri doesn't points to a supported transformation definition or the transformation results in an error an xforms-compute-exception Event or xforms-binding-exception Event will be dispatched.

Examples:

Transform function in submission
<xforms:submission id="s1" ref="transform('my-stylesheet.xsl', instance())" resource="..."/>
Transform function in insert action
<xforms:insert nodeset="n" origin="transform('my-stylesheet.xsl', instance())" />

Transform URIs and Instances

There may be occasions where the transform resides within an XForms instance, for example:

  • The transform is potentially large so it would be more efficient to download it when the form is being constructed rather than upon demand of the initial transform
  • The transform is the result of another transform, e.g. the default Schematron implementation genrates an XSLT transform from the original schema definition.
  • The transform is augmented by user input before being applied to the instance data
  • There are other aspects of the transform's retrieval, over HTTP, that require the richer facilities of an xf:submission in order that it may be dereferenced correctly.

With this in mind, it would be necessary to provide a version of, or option within, the transform function to reference a transform residing in an XForms instance. There is no means of overloading the function by argument type so there are potentially a number or alternate possibilities:

  1. One function for URIs and another for instances
  2. Use a simple fragment identifier
  3. Allow the use of XPointers in the URI
  4. Provide a new URI scheme for referencing internal resources

One function for URIs and another for instances

As described previously, the function can take a string value as its URI:

Object transform(string, node?)

The same function that accepts an XForms instance as the transform would have the following signature:

Object transform(node, node?)

This presents a problem for the interpretor in how to know what to do. The first uses a URI to reference the transform resource whilst the second would use an XPath expression to reference the instance containing the resource. This leads to the notion of having two separate functions, one for URI references and one for instances.

Possible suggestions for function names include:

URI: transform-uri, transform-from-uri, transform-with-uri

Instance: transform-instance, transform-from-instance, transform-with-instance

However, none of the above examples clearly state the action being performed, there is always some ambiguity as to what it is that is being transformed.

Use a simple fragment identifier

A URI's fragment identifier, when not preceded by a URI path takes its context as the parent document. Therefore, in this simplistic case, the form creator could quite rightly assume that because the transform's instance has an xs:ID of 'bar' that that can be referenced within the form via a fragment identifier.

Transform function using a fragment identifier to reference an internal transform.
<xforms:model>
  <xforms:submission id="s1" ref="transform('#bar', instance('foo'))" resource="..."/>
  
  <xforms:instance id="foo">
    <foo>
      <bar>This is a test.</bar>
    </foo>
  </xforms:instance>

  <xforms:instance id="bar">
    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      ...
    </xsl:transform>
  </xforms:instance>

Allow the use of XPointers in the URI

TBD


Provide a new URI scheme for referencing internal resources

The following example shows the transform function using an non-HTTP URI scheme, nominally defined as 'instance', and what follows is the ID of the referenced xf:instance:


Transform function using a specific URI scheme to reference an internal transform.
<xforms:model>
  <xforms:submission id="s1" ref="transform('instance:bar', instance('foo'))" resource="..."/>
  
  <xforms:instance id="foo">
    <foo>
      <bar>This is a test.</bar>
    </foo>
  </xforms:instance>

  <xforms:instance id="bar">
    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      ...
    </xsl:transform>
  </xforms:instance>

Alternatively one could view this as a URN and reference it thus: urn:instance:bar

The Extended transform() Function (proposal)

It is not unusual for XSLT transformations to make use of parametric data, in addition to the instance being passed. In this proposal, the transformation function defined in the previous section carries a third parameter that is a referenced instance document, with each child of the root instance node being the name of a given parameter and each CDATA section or subordinate XML content being the value or subordinate XML node being passed to the transformation. The extended function is given as the following:

Object transform(

   $URL as string, 
   $dataInstance as node?, 
   $parameterInstance as node?
   )

This functions returns the result of the transformation of the provided XML sub-tree. The returned result can be either a node or a string depending on the result of the transformation. The function performs as the transform() function in the previous section, but additionally uses the $parameterInstance to determine the parameters (including the associated namespaces) and values for the given transformation.

Examples:

Transform function deriving parameters from an external instance.
<xforms:model>
   <xforms:instance id="foo">
       <foo>
          <bar>This is a test.</bar>
       </foo>
   </xforms:instance>
   <xforms:instance id="params">
       <params xmlns:alt="xmlns="http://www.myschema.org/xmlns/alt">
           <name>Jane Doe</name>
           <id>jd125</id>
           <alt:date>2011-06-25</alt:date>
       </params>
   </xforms:instance>
</xforms:model>
<xforms:submission id="s1" ref="transform('my-stylesheet.xsl', instance('foo'), instance('params')" resource="..."/>

In this particular scenario, three parameters are passed to the transformation: name (with a value of 'Jane Doe'), id (with a value of 'jd123') and alt:date (with a value of '2011-06-25'), where alt is in the given namespace. Should there be a parameter in the transformation with the associated name, then it will override any internally defined parameters, otherwise, the variables will be ignored. That is to say,

Example of parameters within the associated stylesheet.
<xsl:stylesheet xmlns="http://www.w3.org/1999/XSL/Stylesheet" xmlns:alt="http://www.myschema.org/xmlns/alt" version="1.0" >
    <xsl:param name="name" select="'John Doe'"/>
    <xsl:param name="id"/>
    <xsl:param name="salary" select="80000"/>
    <xsl:param name="alt:date/>
    <!-- Additional content -->
</xsl:stylesheet>

Once the parameters are passed into the transformation, the parameters will have the name/value hashes of name:Jane Doe, id:jd123, salary:80000, alt:date:2011-06-25, respectively.

Any parameter that is in the xsl: namespace is treated as privileged, and is intended to pass critical information to the transformation itself. For instance, <xsl:mode>alpha</xsl:mode> indicates that the transformation start out in that mode of construction (that is, only <xsl:template> elements that have a @mode attribute value of "alpha" will be evaluated as the first template to be processed). as shown in the following instance example:

Illustration showing the use of xsl: system parameters.
<xforms:model>
   <xforms:instance id="foo">
       <foo>
          <bar>This is a test.</bar>
       </foo>
   </xforms:instance>
   <xforms:instance id="params" xmlns:alt="xmlns="http://www.myschema.org/xmlns/alt" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <params>
           <name>Jane Doe</name>
           <id>jd125</id>
           <alt:date>2011-06-25</alt:date>
           <xsl:mode>alpha</xsl:mode>
           <xsl:mediatype>text/xml</xsl:mediatype>
           <xsl:indent>yes</xsl:indent>
       </params>
   </xforms:instance>
</xforms:model>
<xforms:submission id="s1" ref="transform('my-stylesheet.xsl', instance('foo'), instance('params')" resource="..."/>


The xsl:mediatype overrides the <xsl:output element's @mediatype attribute, and so forth. A full list of these xsl parameters are still TBD, but may include the following.

Name Values Description
xsl:mode any QName Used to indicate that the matching root template must have the given QName for it's @mode attribute. This is frequently used when the same stylesheet might have multiple potential rendering approaches.
xsl:method text or xml or html or binary In the <xsl:output>, this sets the method used for generating the type of output used by the transformation.
xsl:mediatype any mime type, such as text/xml or image/svg+xml In the <xsl:output>, this sets the specific mime type that will be passed to the next processor in the transformation sequence.
xsl:indent yes or no This sets whether the content is pretty printed (yes) or not (no). The default is 'no'.

The parameters list makes use of the same conventions as the GET xforms-submission instance does - the containing instance element is immaterial (save as a place to declare namespaces global to the document), but the children of the parameters to be passed are treated as the parameter value names. It remains TBD as to whether if a parameter has a subordinate XML document that document is passed as the value, or whether this constitutes an error for the processor.

References

Normative references

xforms-compute-exception
TODO
xforms-binding-exception
TODO