Monday, May 17, 2010

XQuery to change the local name of an element

returning to the problem of changing operation in a body, that is turning:

<dbac:insertCompany xmlns:dbac="http://com/acme/dbaccess">
  <dbac:company xmlns:java="java:com.acme.dbaccess">


<dbac:updateCompany xmlns:dbac="http://com/acme/dbaccess">
  <dbac:company xmlns:java="java:com.acme.dbaccess">

of course one way would be to turn all the payload into a String, do a fn:replace(thestring, oldoperation, newoperation) and then turning it back into a element(*); but it's very unsafe as it replaces everything.

There is a reliable way using this XQuery:

declare namespace functx = "";
declare namespace dbac = "http://com/acme/dbaccess";

declare function functx:replace-beginning
  ( $arg as element(*), $name as xs:string,$newName as xs:string)  as element() {
    if (fn:ends-with(string(node-name($arg)), $name) = xs:boolean('true')) then
     Error Message
 } ;

declare variable $arg as element(*) external;
declare variable $name as xs:string external;
declare variable $newName as xs:string external;
functx:replace-beginning($arg, $name, $newName)

This is an excellent demonstration of how to instantiate a node (element($newName)} and insert into it portion of the old element.


rpbarbati said...

Or on the OSB, simply use a rename action - it can rename elements and even inject namespaces.

vernetto said...

true, I have done

define user defined namespace dbac="http://com/acme/dbaccess"

rename ./dbac:updateCompany in variable $body to localname updateCompanyBla

and it works like a charm.

The problem is when you must perform the same operation inside XQuery... I try to manipulate payloads inside XQuery as much as I can, leaving my message flow to the bare minimum...

vernetto said...

now I remember: I needed to rename the element into something that I could decide DYNAMICALLY.... unfortunately the OSB "rename" action forces you to hardcode the "target" name, you cannot pass it as a variable... that's why I needed to do it with a XQuery!