Complex mapping scenarios in BusinessWorks 6.X and BusinessWorks Container Edition

Emmanuel Marchiset
12 min readOct 21, 2021

This blog article is explaining how to manage complex mapping scenarios using the BusinessWorks Mapper.

It is similar to the elements available in the ‘Mapping and Transforming Data’ chapter of the ‘Process Design Guide’ of the BusinesWorks 5.X documentation but adapted for BusinessWorks 6.X and BusinessWorks Container Edition.

The BusinessWorks 5.X documentation is available at the following URL :

https://docs.tibco.com/pub/activematrix_businessworks/5.14.0/doc/html/wwhelp/wwhimpl/js/html/wwhelp.htm#href=tib_bw_process_design/dg.5.066.htm

Using XPath

TIBCO ActiveMatrix BusinessWorks uses XPath (XML Path Language) to specify and process elements of the Activity Input schema. You can also use XPath to perform basic manipulation and comparison of strings, dates, numbers, and booleans.

One of the most common uses of XPath is to filter a list for specific elements. XPath expressions have search predicates for performing filtering. In the Activity Input area, when a search predicate is required, it appears as [<< Filter >>] to indicate that you must supply the filter expression. For example, you may wish to select a specific order from a list of orders where the item ordered is itemID #34129. To do this, the XPath expression might be: $RetrieveOrders/Order[itemID=34129].

You can use any valid XPath expression in the XSLT statements in the Activity Input area.

Merging Input from Multiple Sources

You may have multiple elements in the Process Data that you wish to map to one repeating element in the Activity Input. For example, you may have multiple formats for customer records and you wish to create a single, merged mailing list containing all customers in one format. In this example, the schemas are the following:

The following procedure describes how to map multiple elements into a single repeating element.

#1 Select the repeating element in the Activity Input area, right-click, and select Duplicate from the popup menu.

Because you are creating two different formulas for mapping, you need two copies of the repeating element, one for each format. The resulting output contains only one repeating customer element, but the two copies in the Activity Input area make it simpler to perform two different mappings.

# 2 Map one of the elements from the Process Data to the first copy of the repeating element in the activity input. For example, map $Retrieve-Customer-Type1/Customer to MergeMailingList/CustomerList/Customer.

The Mapping Wizard dialog appears and presents choices for what you would like to accomplish.

Choose the For Each option and click Next.

The mapping wizard asks if you wish to automatically map items with the same names and other options. Click Finish to accept the default mappings.

#3 Map the other element from the Process Data to the second copy of the repeating element in the activity input. For example, map $Retrieve-Customer-Type2/Record to MergeMailingList/CustomerList/Customer.

In the Mapping Wizard dialog, choose the For Each option and click Next.

The mapping wizard presents you with an option to automatically map elements with the same name and other options. Click Finish to accept the default mappings.

# 4 Select the Address element and click the XPath Formula Builder icon in the Input tab toolbar. In the XPath Formula Builder, drag a concat() function into the XPath Formula field. This function is used to concatenate the three elements in the Record element in the process data area to one Address element in the activity’s input.

Click the Data tab, then drag the $Retreive-Customer-Type2/Record/Address/street element into the << string1 >> placeholder in the concat() function.

Drag the $Retreive-Customer-Type2/Record/Address/state element into the << string2 >> placeholder in the concat() function. Then, add a comma to the end of the function to include a third string to concatenate. Drag the $Retreive-Customer-Type2/Record /Address/zip element into the position of the third string in the concat() function.

The ZIP field appears in red while it needs to be converted to a string, for this click on the ‘Fix Type-Casting Error’ button :

# 5 This results in the following mapping:

Converting a List Into a Grouped List

You may need to convert a flat list of items into a more structured list. For example, you may have list of all orders that have been completed. You may want to organize that list so that you can group the orders placed by each customer. This scenario typically occurs when you retrieve records from a relational database and the records must be structured differently.

In this example, the schemas are the following:

The following procedure describes how to map the flat list of orders into a list grouped by customer ID.

# 1 Choose the repeating element in the Activity Input schema that holds the grouped data. In this example, that element is Orders. Right-click on this element and choose Surround with -> Surround with For-Each-Group… from the pop-up menu. This is a shortcut to create a For-Each-Group statement with the Orders element as a child element and a Grouping statement to contain the element you wish to group-by.

# 2 Drag the repeating element from the Process Data area to the For-Each-Group statement.

# 3 Drag the element you wish to group by from the Process Data area to the Grouping statement in the Activity Input area. In this example, customerID is the grouping element.

# 4 Choose the repeating element in the Activity Input schema that holds the details for each group. In this example, that element is Order. Right-click on this element and choose Surround with -> Surround with For-Each… from the pop-up menu.

The Order element now refers to the current-group() :

# 5 Map the customerID element in the Requests element into the Customer element in the Activity Input area.

Map the Quantity and ItemName fields as needed.

This results in the following mapping:

Merging Two Corresponding Lists

You may need to merge two lists that have corresponding items. For example, you may have a list of student IDs and a list of grades, each grade corresponds to the student ID in the same position in the student ID list. In this example, the schemas are the following:

The following procedure describes how to merge the two repeating elements containing corresponding data into one repeating element.

# 1 Map the first repeating element from the Process Data area into the Grades repeating element in the Activity Input area. In this example, the $RetrieveStudentIDs/Students/Record is the first repeating element.

This brings up the mapping wizard with the default choice of creating a For-Each statement.

Click Finish in the Mapping Wizard dialog to create the For-Each statement.

Merging two parallel repeating structures requires two variables. One variable is to hold the position number of the current item being processed, and the other variable is to hold the item in the second list that corresponds to the position of the item in the first list. Create the variables following the next steps.

# 2 Create an ‘item’ Variable under the Grades repeating element using the Add Child -> Variable pop-up menu :

# 3 Create an ‘index’ Variable under the Grades repeating element using the Add Child -> Variable pop-up menu :

# 4 Set the index variable with the value ‘position()’

The $=[index=] element contains the XPath formula position() to set the element with the current position number of the list item being processed.

# 5 Set the item variable with the corresponding item from the second list ($RetreiveGrades)

Then set the Filter to $index :

The $=[item=] element contains a statement to retrieve the item in the second repeating element that corresponds to the position of the item in the first list that is currently being processed.

# 6 Map the ID element to the StudentID element in the Activity input.

# 7 Map the $=item/Grade element to the Grade element in the Activity Input area.

This results in the following mapping:

Coercions

In some situations, the datatype of a Process Data element may be undefined. In these situations, you may know the datatype of the element, and you can coerce the element into a specific type. The Add / Edit Coercions context menu available in the Data Source tab allows you to create and manage your coercions.

The following example illustrates a schema with an element defined as the “any element” datatype. The schema is for a generic incoming message that can have any type of body. In the example, however, the any element is coerced into an Order type so that it can be mapped to a choice element.

In this example, the schemas are the following:

The following procedure describes how to coerce the Body element of the incoming message into a specific datatype and map it to a choice element.

There are different ways of accomplishing the same result as this example. This example attempts to illustrate the simplest method to achieve the desired result.

# 1 Define the coercion to use for the element of type ‘Any’ using the Add/Edit Coercion… pop-up menu

In the Coercions dialog, click the Insert button (+) to add a coercion for the currently selected element.

Then select the type to use in the coercion :

Click OK to coerce the element into the datatype of the selected schema element. The following would be the resulting schema where the element of the datatype any element has been replaced with the Order schema.

# 3 Map the Name element to the Name element in the Activity Input area. Then, map the coerced Order element to the choice element in the Activity Input area.

The Mapping Wizard dialog appears and asks if you wish to create an Order or a CreditLimitIncrease element. Select Order and click Next.

# 4 Map the Item and Amount fields has needed

The following is the completed mapping :

#5 Additional note on management of Choice

If you want to define how a ‘Choice’ element will be managed in the Input tab of the Mapper you can do it by dragging this element to the left :

The Mapping Wizard dialog appears and asks if you wish to create an Order or a CreditLimitIncrease element. Make your choice and click Next (for example CreditLimit in this case).

The Input tab of the Mapper now look like this :

Setting an Element Explicitly to Nil

In some situations, you may wish to set an element explicitly to nil. One situation is when you wish to insert a row into a database table and you wish to supply a NULL for one of the columns. To set an input element explicitly to nil, perform the following:

#1 Map something the target element (‘item’ in the example below)

# 2 Open the XSLT editor

And select the XSLT Source tab

# 3 Edit the XSLT code to map the nil value

# 4 Close the XSLT Editor

Click on the ‘Parse’ button:

This results in the following mapping:

Note the line going to the ‘item’ element is showing that the element is mapped.

Sorting a list

It is possible to use the mapper to sort a list.
In the example below there is need to sort the list of Requests.

This can be done with the following:

#1 Drag and drop the list of Requests to be sorted on the list of Requests in the Input tab

#2 Select the ‘For each .. create a “Requests” option

Then click Next

#3 Select Mapping options

If the sorting is to be done on elements located at the root level of the list the default options can be kept.

Once done click ‘Finish’.

#4 The mapping should now look like this

#5 Open the ‘Edit’ tab

Click on the ‘Show/Hide Edit tab’ button

#6 Add the sort statement after the for-each

Example of a sort statement specifying that the sort should be done on the quantity field and on descending order:
<xsl:sort select=”tns:quantity” order=”descending” />

Details on the available sort options are available here:
https://www.w3schools.com/xml/ref_xsl_el_sort.asp

# Click on Parse and close the ‘Edit’ tab

You can now see the Sort statement in the Mapping.

--

--

Emmanuel Marchiset

I work as an Architect at TIBCO Software on Integration products. Opinions here are my own.