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">
    <java:CreationDate>3</java:CreationDate>
    <java:Id>10</java:Id>
    <java:Name>string</java:Name>
  </dbac:company>
</dbac:insertCompany>



into

<dbac:updateCompany xmlns:dbac="http://com/acme/dbaccess">
  <dbac:company xmlns:java="java:com.acme.dbaccess">
    <java:CreationDate>3</java:CreationDate>
    <java:Id>10</java:Id>
    <java:Name>string</java:Name>
  </dbac:company>
</dbac:
updateCompany>


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 = "http://www.functx.com";
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
     element{$newName}{$arg/node()}      
    else
     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.

3 comments:

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!