XQuery/Generating Skeleton Typeswitch Transformation Modules

Motivation
For document types which contain multiple tags, such as TEI or DocBook, it is tedious and error-prone to write this conversion code by hand. We can use XQuery to generate the basic text for an XQuery module.

This article uses the same example as used in ../Transformation idioms/.

Example
Starting with a simple list of the tags in this document, we can generate a module which performs an identity transform on a document containing these tags.

Here is the XML output and the text XQuery file created by adding the line to the script.

If we save this script as, say coupid.xqm, we can use it to generate the transformed document:

Generate

We can also check if the identity transformation has retained the full structure of the document:

Compare

Module design
The generated module looks like this:

The function convert($nodes) contains the typeswitch statement to dispatch the node to one of the tag functions. Each tag function creates an element of that name, copies the attributes and then recursively calls the convert function passing the child nodes. The default action defined in the function convert-default merely copies the node.

Generation Function
This function generates the code for an XQuery module which performs an identity transformation.

There are two parameters
 * tags - a sequence of tags
 * config - an XML node containing definitions of the module name, module prefix and module namespace.

Generating the tags
All tags in the document or corpus need to be handled by the identity transformation, so it would be better to generate the list of tags from the document or corpus itself. The following function returns a sequence of tags in alphabetically order.

and we can modify the calling script:

Generate

User-defined function template
The module generator function generates a fixed code pattern for each tag. We can allow the user to customize this pattern by using a callback function to generate the code pattern as an alternative to modifying the generator code itself.

The modified function code has the following modifications:

Function signature ; generating each tag function:

To generate a basic transformation to HTML, with HTML elements being copied while non-HTML elements are converted to div elements with an additional class attribute, we define the function to create the code body, create the function reference and call the convert function:

else };

declare option exist:serialize "method=text media-type=text/text";

let $doc := doc("/db/Wiki/eXist/transformation/Coupland1.xml") let $tags := gen:tags($doc) let $callback := util:function(QName("http://www.cems.uwe.ac.uk/xmlwiki/x","fx:tag-code"),2)

let $config := coupland http://www.cems.uwe.ac.uk/xmlwiki/coupland return gen:create-module($tags, $callback, $config)

Generate

Customising the generator
Another customization of the generator which may be required is to add an additional $options parameter to all signatures and calls. This provides a mechanism for passing configuration parameter around the functions to control the transformation.

Transforming with XSLT
When the conversion is complex, requiring restructuring, context-dependent transformations and reordering, it is not clear that the XQuery typeswitch approach is better or worse than the XSLT equivalent. For comparison here is the equivalent XSLT.

and XQuery to apply this server-side:

Transform to HTML via XSLT