Scenario
By: Lachlan Aldred
A purchase order arrives from a trading partner. Two new documents need to be created using it:
- A billing document that contains the billing address and the total cost of the purchase.
- A shipping document that contains the ship-to address the list of items, and the address of the shipper.
To create the billing document we need to process the incoming purchase order and calculate the total cost by calculating the sum-total of each line item, and its quantity. We also need to include the bill-to address in the PO.
To create the shipping document we need to extract the ship-to address and each line item from the purchase order. Furthermore we need to merge this data with our own preferred shipper address.
XSLT is a powerful XML transformations language capable of performing this task, however most non-experts find it difficult to write correct XSLT scripts. XQuery is much more concise, and easier to learn, particularly for people familiar with SQL. In this case we use an XQuery Component to perform the transformations.
 | About XQuery
XSLT is the state-of-the-art technique for complex merges, extractions and transformations of XML, however, its XML syntax is highly verbose, and extremely difficult for non-experts to write. The Word Wide Web Consortium (the standards organization behind XSLT) recognized these challenges and decided to create a simpler XML merging/transformation language for the rest of us to use – XQuery. |
The Process
A process that produces a shipping document and a billing document is shown below. It uses PO1v80.xml, taken from the w3c website, as an input purchase order.

There are two operations in the XQuery component. One can take as input an XML, XFA, String, or Document variable. It can then transform the XML contents into anything else. The other takes as input all of the XML, XFAForm, and XML-String variables in the process-instance data. This way it can easily merge the contents of two XML variables together.
To prepare the billing statement required us to multiply cost of each line item with its quantity; and to total the results. Below is the XQuery we used to do this:
<avoka:billingStatement>
{//billTo}
<total>$ {
sum( for $i in //item
return ($i/quantity * $i/USPrice) )
}</total>
</avoka:billingStatement>
Without going into details of the XQuery language too deeply, we extracted the billTo section of the incoming PO, and wrapped the results of our calculations in 'total' tags. The parentheses indicate that the contents are executable XQuery instructions, and the surrounding markup outside these same parentheses is copied literally into the resulting XML document (below).
<avoka:billingStatement xmlns:avoka="http://www.avoka.com">
<billTo xmlns:apo="http://www.example.com/PO1" country="US">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</billTo>
<total>$ 944.6500000000001</total>
</avoka:billingStatement>
The xmlns:avoka="http://www.avoka.com" is set in the process properties. The component pulls in the process properties and reuses those namespaces, if necessary.
The XQuery step "Prepare Shipping Request" uses the XML merge functionality of the XQuery component.
There are 2 known issues in using the XQuery Component:
- When using the XQuery Merge operation the input document/s should not contain any XML comments <!-- ... -->. The XML parser seems to have difficulty in reproducing them back into literal form, and seems to output them as <# comment>.
- Although the XQuery component can handle namespaces, the XPath builder widget on the GUI doesn't include them in the xpath expression it creates. So if one of the steps in your XPath expression needs to be namespaced then you will need to add it manually.
An LCA file of the process is available from here.
This process uses no initial form. To launch it you would need to invoke it by embedding it in your own process, or by launching it from within Workbench.
This process is a toy example. In actuality the first steps would be replaced with an input parameter of type PurchaseOrder.