Adding namespace to a no namespace XML using XQuery

I recently worked with a customer where their XML standards state that all XML instance documents should be namespace qualified. I was converting a flat file to XML using MFL Transform which doesn’t set a namespace for the transformed XML. The below Xquery can be used to add a namespace to all element nodes in a no namespace XML instance document like the mfl transformed xml.

xquery version "1.0" encoding "Cp1252";
(:: pragma parameter="$noNamespaceXML" type="xs:anyType" ::)
(:: pragma parameter="$namespaceURI" type="xs:string" ::)
(:: pragma type="xs:anyType" ::)
declare namespace xf = "<a href="http://tempuri.org/Resources/XQueries/addNamespace/">http://tempuri.org/Resources/XQueries/addNamespace/</a>";
declare function xf:addNamespaceToXML($noNamespaceXML as element(*),$namespaceURI as xs:string) as element(*)
{
element {fn:expanded-QName($namespaceURI,fn:local-name($noNamespaceXML))}
{
$noNamespaceXML/@*,
for $node in $noNamespaceXML/node()
return
if (exists($node/node())) then xf:addNamespaceToXML($node,$namespaceURI)
else if ($node instance of element()) then element {fn:expanded-QName($namespaceURI,fn:local-name($node))}{$node/@*}
else $node }
};

declare variable $noNamespaceXML as element(*) external;
declare variable $namespaceURI as xs:string external ; 
xf:addNamespaceToXML($noNamespaceXML, $namespaceURI)

The above code recursively access all nodes in the xml instance, checks if the node is an element node and qualifies the element node with the passed namespaceURI. Other type of nodes ( text, attributes etc) are not namespace qualified.
$noNamespaceXML

<a>
<b attr="attribute">text</b>
</a>

$namespaceURI

http://www.abc.com

returns

<ns:a xmlns:ns="www.abc.com">
<ns:b attr="attribute">text</ns:b>
</ns:a>

I’ve learnt two points when doing this.

First, OSB doesn’t support fn:QName (function belonging to Xpath domain) which allows namespaceURI and localname as the parameters to create a new namespace qualified element. OSB supports xs:QName (function belonging to xsd domain) which doesn’t serve the same functionality. Instead we need to use fn:expanded-QName() to create elements dynamically.

Second, attribute nodes are not child element of element nodes.

<ns:b attr="attribute">text</ns:b>

If you apply node() function on the element node it returns only the text node “text” and not the attribute node “attr=attribute”. This W3C School link gives the relationship between different nodes and is a useful reference.

Advertisements

About atheek

I am a Weblogic consultant working in Middleware/Integration area.
This entry was posted in OSB, XQuery and tagged , , . Bookmark the permalink.

3 Responses to Adding namespace to a no namespace XML using XQuery

  1. Noufal says:

    Good work! Atheek,
    I was looking at below in your code:
    Ln1: if (exists($node/node())) then xf:addNamespaceToXML($node,$namespaceURI)
    Ln2: else if ($node instance of element()) then element {fn:expanded-QName($namespaceURI,fn:local-name($node))}
    Ln3:{$node/@*}
    Ln4: else $node }

    The documentation states that element() is an element node, while node() is any node, so if I understand it correctly element() is a subset of node().
    This means the xquery works fine without the Ln2:”else if” stmt.
    Also, Ln3: is not needed, as element node would be the container of leaf node (ie. data node => text) and nowhere to dig beyond it.
    This functionality is managed by the recursively call to function “xf:addNamespaceToXML($node,$namespaceURI)” in Ln1

    cheers,
    Noufal

    • atheek says:

      Ln1 : is checking for child elements to drill down to leaf nodes
      Ln2 : is applying the namespace when a leaf node is an element

      Ln3: is for attributes not text node .. attributes are not considered child elements of element node

  2. Freddy says:

    Great, thank you!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s