Orbeon Forms User Guide

Using the Orbeon Forms XUpdate Engine in Java

1. Scope

Orbeon Forms applications use the XUpdate processor to perform XUpdate transformations. The Orbeon Forms XUpdate engine implements the JAXP API that can be used directly by Java programs for experimentation purposes. This section describes the JAXP interface exposed by the Orbeon Forms XUpdate engine. We assume here that you are familiar with the basics of the JAXP APIs.

2. API

Note: The JAXP methods described in this section are the only ones supported by Orbeon Forms.

2.1. Creating a Templates

  1. Create an instance of org.orbeon.oxf.transformer.xupdate.TransformerFactoryImpl. This class extends javax.xml.transform.sax.SAXTransformerFactory.
  2. Call newTemplatesHandler() on the factory. This returns an instance of javax.xml.transform.sax.TemplatesHandler.
  3. A TemplatesHandler implements that SAX ContentHandler interface. Feed this content handler with the XUpdate program.
  4. Call the getTemplates() method on the templates handler. This returns an instance of javax.xml.transform.Templates. This object contains the internal representation of the XUpdate program.

2.2. Performing a Transformation

  1. Call newTransformer() on the Templates object. This returns a javax.xml.transform.Transformer
  2. Call transform() on the transformer by passing a SAXSource and SAXResult as arguments.

3. Running Your Program

To run your program, you need to have the following JAR files in your classpath:

  • Orbeon Forms: orbeon.jar
  • dom4j: dom4j-1_4.jar
  • Jaxen: jaxen-1_1-beta-1-dev.jar
  • SAXPath: saxpath-dev_orbeon.jar
  • Xerces: xercesImpl-2_2_1_orbeon.jar
  • XML APIs: xml-apis-2_5_1.jar

To get those JAR files:

  1. Download Orbeon Forms
  2. Extract ops.war from the ZIP archive.
  3. Extract the JAR files from the WAR archive. They are stored in the WEB-INF/lib directory.

4. Sample Driver

4.1. Source Code

package org.orbeon.oxf.transformer.xupdate;

import org.apache.crimson.parser.XMLReaderImpl;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXContentHandler;
import org.dom4j.io.XMLWriter;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import javax.xml.transform.Templates;
import javax.xml.transform.TransformerException;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TemplatesHandler;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class XUpdateDriver {

    private final static String XUPDATE_FACTORY =
            "org.orbeon.oxf.transformer.xupdate.TransformerFactoryImpl";

    public static void main(String[] args) throws TransformerException, IOException {

        // Check arguments
        if (args.length != 2) {
            System.err.println("Syntax: java " +
                    XUpdateDriver.class.getName() + " input.xml xupdate.xml");
            return;
        }

        // Perform transformation
        Templates templates = createTemplates(new FileReader(args[1]));
        SAXContentHandler saxContentHandler = new SAXContentHandler();
        templates.newTransformer().transform(new SAXSource(new XMLReaderImpl(),
                new InputSource(new FileReader(args[0]))),
                new SAXResult(saxContentHandler));

        // Output result
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setIndentSize(4);
        XMLWriter xmlWriter = new XMLWriter(System.out, format);
        xmlWriter.write(saxContentHandler.getDocument());
    }

    private static Templates createTemplates(Reader xupdateReader) {
        try {
            SAXTransformerFactory factory = (SAXTransformerFactory)
                    Class.forName(XUPDATE_FACTORY).newInstance();
            TemplatesHandler templatesHandler = factory.newTemplatesHandler();
            XMLReader xmlReader = new XMLReaderImpl();
            xmlReader.setContentHandler(templatesHandler);
            xmlReader.parse(new InputSource(xupdateReader));
            return templatesHandler.getTemplates();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

4.2. Running the Driver

You can run the driver with java org.orbeon.oxf.transformer.xupdate.XUpdateDriver input.xml xupdate.xml. Make sure to have in your CLASSPATH the JAR files listed earlier. Assuming that input.xml contains:

<company><year id="2000"><quarter id="1" sales="80"/><quarter id="2" sales="56"/><quarter id="3" sales="97"/><quarter id="4" sales="150"/></year><year id="2001"><quarter id="1" sales="20"/><quarter id="2" sales="54"/><quarter id="3" sales="80"/><quarter id="4" sales="90"/></year><year id="2002"><quarter id="1" sales="54"/><quarter id="2" sales="65"/><quarter id="3" sales="96"/><quarter id="4" sales="164"/></year></company>

And xupdate.xml contains:

<xu:modifications xmlns:xu="http://www.xmldb.org/xupdate"><xu:function name="double"><xu:param name="f"/><xu:function name="result"><xu:param name="x"/><xu:value-of select="f($x) * 2"/></xu:function><xu:copy-of select="$result"/></xu:function><xu:function name="increment"><xu:param name="x"/><xu:value-of select="$x + 1"/></xu:function><xu:variable name="incrementAndDouble" select="double($increment)"/><xu:update select="/"><result><xu:value-of select="incrementAndDouble(2)"/></result></xu:update></xu:modifications>

Then the output on the console will be:

<result>6</result>