Wednesday 20 July 2011

XQuery translations to Oracle Service Bus

So things are never as straight forward as they should be when Oracle Service Bus gets involved. It isn't possible to include modules in OSB XQuery... It is also difficult to include arbitrary documents without referring to an absolute path (deployment nightmare!); this was needed to refer to the 'translation table' XML file.

So I created a XQuery script compatible with Oracle Service Bus that does the following:
- Takes a node
- Takes a list of node names (including namespaces) that we want to convert
- A translation table as before
=> We return the provided node with the nodes in the node name list translated into the new values.

declare namespace tmp = "http://www.tempuri.co.nz/xquery/";

declare function tmp:convertString($inputString as xs:string, $translationSet as element()*) as xs:string {
        if (count($translationSet) = 0) then (: base case :)
           $inputString
        else (: recursion :)
           let $fromValue := data($translationSet[1]/translate_from)
           let $toValue := data($translationSet[1]/translate_to)
           let $updatedStr := fn:replace($inputString,$fromValue,$toValue)
           return tmp:convertString($updatedStr,remove($translationSet,1))
};

declare function tmp:replaceAll($element as element(), $updateNodes as xs:string*, $translationSet as element()*) as element() {
        element { fn:node-name($element) }
                     { $element/@*, for $child in $element/node()
                                    return if ($child instance of element())
                                           then tmp:replaceAll($child, $updateNodes,$translationSet)
                                           else if ($child instance of text() and count(index-of($updateNodes,fn:name($element))))
                                                then tmp:convertString($child,$translationSet)
                                                else $child
                     }
};

declare variable $element as element() external;
declare variable $updateNodes as xs:string* external;
declare variable $translationSet as element() external;

tmp:replaceAll($element, $updateNodes, $translationSet//translation)

Then in Oracle Service Bus I created a request/response pipeline at the very start with a replace node in each stage. The XPath is simply '.' in the variable body, with the XQuery created above. The external variables above are as follows:
translationSet:

        
          A
          BB
        
        
          C
          DD
        



updateNodes:
"firstname","lastname"

element:
$body

This will take the $body node, and find all nodes called "firstname" and "lastname", replacing all "A"'s and "C"'s with "BB" and "DD" respectively. Obviously strange characters will be more useful ;).

1 comment:

  1. How many stages do you have in the message flow?
    i.e., nbr of replace nodes

    ReplyDelete