Wednesday, January 30, 2008

Name-value Pair Transformation in BPEL

A pattern you often see is that some generic message type containing a number of 1..n name-value pair attributes needs to be transformed to specific attributes of a specific message type. For example, a portal of a some local government accepts a range of service requests that need to be transformed to a specific request for a passport, a parking permit and so on, to be able to be processed by specialized back-office systems.

The generic message type could for example be defined in an ServiceRequestForm.xsd as follows:


As you can see, the name-value pair attributes are passed on a a repeating set of formItems.

Let's assume that the specific type of message it needs to be transformed to, is based on the value of the serviceType attribute. In case the value of that attribute is "passport request" the ServiceRequestForm needs to be transformed to a PassportRequest.xsd consisting of the following attributes:


Now let's assume we are using BPEL to process the messages and let's assume no performance reason is keeping us from using an (XSLT) transformation (Transform) instead of a series of copy actions in an Assign. So for passports we create a transformToPassportRequest.xsl in which we would like to map the formItems at the left side of the following picture to the specific name, address and city attributes at the right side.


The simplest way to achieve this is by creating a so-called user-defined XSLT template that takes the name of an attribute as argument and transform the corresponding generic name-value pair attribute to the specific attribute. To this purpose we put a template called "getItemValue" at the bottom of the XSL file, as follows:


After you have done so, you will will find the getItemValue template in the User Defined Named Template drop-down in the component pallet of the XSL editor.


After you dragged & dropped that template from the component pallet in the middle section of the mapper, you can create a link from the formItem attribute to the template and from the specific attribute to the template, as has been done for the address attribute in the following figure:


To make that the template transforms any formItem attribute for which its name attribute has the value "address" you need to pass in 'address' as argument.


In a similar way you can transform formItem to the two remaining attributes, finally resulting in something like the following:


Ah... if everything would be as simple at this!

4 comments:

jwbroek said...

Hey Jan. Your template can be even simpler (and likely a bit more performant), by using XPath rather than a loop.

You can do this by getting rid of the loop and everything in it and instead just using:

<xsl:value-of select="$item[ns1:name=$itemName]/ns1:value"/>

This basically says: take any items such that they have a name element equal to itemName, and from these items, take the value child.

As you can see this is a purely functional way to go about it, rather than a procedural approach, which in itself is somewhat nifty :-)

Jan Kettenis said...

Come to think of it, looking at it I wonder why I put the for-each in there in the first place! Good addition, thank you!

Anonymous said...

I like a game which needs to use wow gold, when you do not have World of Warcraft Gold, you must borrow warcraft gold from friends, or you buy wow gold. If you get cheap wow gold, you can continue this game.

niroa said...

Wow, there is a lot of worthwhile material above!