XUpdate Processor
- 1. Scope
- 2. About XUpdate
- 2.1. Origin
- 2.2. The Orbeon Forms XUpdate Engine
- 2.3. Best Practices
- 3. Language Reference
- 3.1. Standard elements
- 3.2. Extensions
- 3.3. Incompatibilities
- 3.4. XPath
- 4. Using the XUpdate Processor
- 4.1. Interface
- 4.2. Using Multiple Documents
- 5. Examples
1. Scope
This section provides an overview of the XUpdate language, the Orbeon Forms XUpdate engine, and the extensions to the XUpdate language supported by the Orbeon Forms XUpdate engine. It also features examples programs written in XUpdate.
For more information on how to use the Orbeon Forms XUpdate engine directly from Java programs, see the XUpdate section in Integration.
2. About XUpdate
2.1. Origin
The XML:DB group has been working on a specification for a language to describes how to update an XML document. The latest version of the XUpdate specification was released in 2000 as a working draft. Since then, XUpdate has been used in a number of situations to update XML documents, in particular in XML databases like eXist, Xindice and X-Hive/DB.
2.2. The Orbeon Forms XUpdate Engine
XUpdate does not provide means to declare variables, iterate over a node set, or declare functions. In addition to the XUpdate specification, the Orbeon Forms XUpdate engine implements a set of extensions to allow all of the above.
The XUpdate language was designed to be consistent with XSLT, so it would be natural for developers who are familiar with XSLT to use XUpdate. The extensions to the XUpdate specification implemented in the Orbeon Forms XUpdate engine follow the same design principle as they closely mimic their XSLT counterpart.
2.3. Best Practices
An XUpdate transformation is similar to an XSLT transformation:
- As shown in the illustration below, just like XSLT, XUpdate transforms an XML input document into an XML output document based on a "configuration". With XSLT, the configuration is an XSLT stylesheet. With XUpdate, the configuration is a program written in the XUpdate language.
- The XSLT and XUpdate languages have similar expressive power, they both use XPath as the expression language and share elements names in a consistent way.
Every program written in XSLT could also be written in XUpdate and vice versa. A natural question would be: when is it more appropriate to use XUpdate and when is it more appropriate to use XSLT? XSLT and XUpdate are set apart by their distinctive processing model: in XSLT nodes from the input document trigger the execution of templates that define the output document, while an XUpdate provides the sequence of operations to be performed on the input document to create the output document.
As a rule of thumb, XUpdate is more appropriate when the output document is similar to the input document, while XSLT is more appropriate when the output document is a new document in which values from the input document are inserted. This can be summarized in the table below:
XSLT | XUpdate | |
---|---|---|
Execution model | Nodes from the input document trigger the execution of templates that define the output document | XUpdate provides a sequence of operations to be performed on the input document to create the output document |
Most appropriate when | When the output document is a new document in which values from the input document are inserted | When the output document is similar to the input document |
Typical applications | XSLT can be used as a template language, for instance to create an HTML page with both dynamic and static data. The input document contains the dynamic data. The stylesheets contains the static data and describes how the dynamic data is inserted in the document. Doing the same thing in XUpdate would be unnecessarily complicated. |
XUpdate can be used as an annotation language, for instance to validate elements of an input document and to add an attribute on those elements stating if they are valid or not. Another usage is when annotating an XML document to add calculated values based on existing values. Some of the examples below do exactly that. Some cases, for instance when a parent elements has to be updated based on updates previously done to child elements, cannot be handled with XSLT 1.0 without using XSLT extensions or pipelining multiple stylesheets. |
3. Language Reference
All the XUpdate elements mentioned here must be in the
http://www.xmldb.org/xupdate
namespace and for
brevity we use the xu
prefix.
3.1. Standard elements
The elements below are defined in the XUpdate specification.
<xu:modifications version="1.0">
<xu:value-of select="expression">
<xu:if test="expression">
<xu:insert-before select="expression">
<xu:insert-after select="expression">
<xu:append select="expression" child="expression">
<xu:remove select="expression">
<xu:update select="expression">
-
<xu:variable name="qname" select="expression">
<xu:element name="qname">
<xu:attribute name="qname">
3.2. Extensions
-
<xu:function name="qname">
? Defines a function with the given name. The element can contain<xu:param name="qname" select="expression">
elements that define the parameters of the function. Functions defined with<xu:function>
are called from XPath expressions, just like regular XPath functions.Functions in XUpdate, just like variables, can be declared anywhere, not only at the top level. In particular, they can also be declared inside other functions. The visibility rules for functions are the same as those for variables: a function has a visibility on the context where it is declared and is visible only inside the block where it is declared.
Functions in XUpdate are first-class citizen: just like variables they can be passed as arguments and returned by other functions. An example later in this section illustrates how this works.
-
<xu:choose>
? Contains one or more<xu:when test="expression">
elements and an optional<xu:otherwise>
. The content of the first<xu:when>
where the test condition is true is executed. If none is true, the content of<xu:otherwise>
is executed if present. -
<xu:copy-of select="expression">
? Performs a copy of what is returned by the select expression. Unlike<xu:value-of>
, the result of the expression is not converted to a string before it is returned. -
<xu:for-each select="expression">
? Iterates over the node set returned by theselect
expression and executes the content of the<xu:for-each>
for every node in the node set with that node as the current context.Note that in the case below, the content of the
data
variable is updated, not the input document (so in this case, the input document will be left unchanged):<xu:modifications xmlns:xu="http://www.xmldb.org/xupdate"><xu:variable name="company" select="document('oxf:/xupdate/input.xml')"/><xu:for-each select="$company/company/year"><xu:variable name="position" select="position()"/><xu:update select="/company/year[$position]"><xu:value-of select="@id"/></xu:update></xu:for-each><!-- Statements using $company --></xu:modifications> -
<xu:while select="expression">
? Executes the content of the<xu:while>
while the condition in theselect
expression is true. -
<xu:assign select="expression">
? Replaces the content of a variable. Once the value of a variable is set, it is possible to update parts of its contents with statements like<xu:update>
. However no other statements we'll let you replace the root element of the variable, or the value of the variable if it is a simple type. To do so you need to use<xu:assign>
. The new value can be a either specified as an XPath expression with theselect
attribute, or in the contents of the<xu:update>
element. -
<xu:message>
? Just like<xsl:message>
, logs the content of the element. For instance, to log the document being currently updated, use<xu:message><xu:copy-of select="/*"/></xu:message>
. -
<xu:error>
? The XUpdate program is interrupted as an exception is thrown with the result of the evaluation of the element content. -
<xu:namespace>
? Adds a namespace declaration on the current element, just like the XSLT<xsl:namespace>
.
3.3. Incompatibilities
-
The
<xu:value-of>
as described in the XUpdate specification works like the XSLT<xsl:copy-of>
but the XUpdate specification provides no equivalent to the XSLT<xsl:value-of>
.We find this situation both confusing and restrictive. It is confusing because more people know about XSLT than XUpdate and they will be surprised if
<xu:value-of>
has a different behavior than the one they expected. It is restrictive because the XUpdate specification provides no equivalent to the XSLT<xsl:value-of>
functionality.For these reasons the Orbeon Forms XUpdate engine implements both
<xu:value-of>
and<xu:copy-of>
as in XSLT.
3.4. XPath
In a number of places you can use XPath expressions. In addition to standard XPath 1.0, you can use the following list of extension functions:
-
The XPath 2.0 function
get-namespace-uri-for-prefix()
is supported (the XPath engine is still 1.0 compliant, not 2.0). -
evaluate(xpath, namespaces, nodeset)
? Evaluates the first string argument as an XPath expression in the context of the third nodeset argument. Any prefix used in the XPath expression must be defined in the second argument, which is a nodeset of namespace nodes.
4. Using the XUpdate Processor
4.1. Interface
The XUpdate processor has the same interface as the XSLT
processor. It takes two inputs: config
, the
XUpdate program, and data
, the document to
update. In XPL, the XUpdate processor can be invoked with:
4.2. Using Multiple Documents
It is not uncommon that a given document needs to be updated based on information stored in other documents. For example, in the situation illustrated below the document on the left is modified based on three other documents a, b and c.
When calling the XUpdate processor from XPL, this is done
by connecting the three documents to the inputs of the
XUpdate processor named a, b and c.
Then the XUpdate program has access to those documents
through XPath expressions with the document()
or doc()
functions using the URI
#a
, #b
and #c
. Note
that any name can be chosen except data
and
config
since those are reserved for the
document to update and the XUpdate program. Invoking the
XUpdate processor in this scenario could be done as follows:
5. Examples
5.1. Input Document
All the examples have been designed to the work on the sample document given below. This document provides numbers reflecting the sales of a company divided by quarter and by year.
5.2. Leaf to Root Document Annotation
The goal is to add a change
attribute to the
quarter
element with the difference between the
numbers for that quarter and the same quarter one year
before. We also want to add a change
attribute
to the year
element computed as the sum of the
change
attributes on its children elements.
Obviously no change
attribute can be added to
the year
and quarter
elements of
the first year. The output document looks like:
What is particular in this example is that the most convenient way to implement the requirement is to first add an attribute to a set of elements (quarters) and then to update the parent elements (years) based on the values previously computed. This is typically hard to do in XSLT, but is quite natural in XUpdate:
5.3. Iterative Document Annotation
The idea is to add a change
attribute to the
quarter
elements, like in the previous example.
In addition, a variation
attribute must be
added to the quarter
elements with the
difference between the change
value of the
current quarter and the change
value of the
previous quarter. Obviously, the variation
attribute cannot be added to the first quarter of the second
year. The output document looks like:
What is special in this example, is that the most natural
way to implement the requirement is in a two-pass algorithm:
first add the change
attribute, then the
variation
attribute based on the value
previously computed. Iterative algorithms can be implemented
in XSLT but the exercise adds unnecessary complexity and
often requires the use of XSLT extensions or multiple
pipelined XSLT stylesheets. Instead, iterative algorithms
can be expressed very naturally with XUpdate:
5.4. Simple Functions
The XUpdate program below adds a change
attribute on the quarter
elements just like the
previous two examples. But, in this case, the logic to add
the change
attribute to a given element is in a
function and that function is called from some code that
iterates over the quarters. Here, functions are used in
XUpdate just like they would be used in XSLT 2.0.
5.5. Functions as First-Class Citizens
The Orbeon Forms XUpdate engine allows for top-level functions called from XPath expressions, like XSLT 2. Additionally:
- Functions can be declared anywhere in the program, including inside other functions. The visibility rules for functions are the same as those for variables.
- Functions can be assigned to variables, passed as arguments to other functions and returned by functions. Languages providing this capability are said to treat functions as first-class citizen.
The XUpdate program below adds a change
attribute to the quarter
elements just like the
previous examples. The add-change
function is
taken from the previous example. In addition, the logic to
iterate over the quarters has been coded in a function
apply-on-quarter
that takes one argument: the
function to apply to each quarter.
The example below uses the full power of the Orbeon Forms XUpdate engine first-class citizen functions:
At the top level, the above XUpdate program defines two functions:
-
increment
simply takes a number x as argument and returns x + 1 -
double
is more interesting: its argument is not a number but a function f with one argument.double
returns a function g such as g(x) = 2*f(x). Note that to return a function from another function, you must use<xu:copy-of>
and not<xu:value-of>
.
Finally we create a function
incrementAndDouble
by applying
double
on increment
. As expected
the result of incrementAndDouble(2)
is 6: