Example: Changing the namespace prefix of an element

These examples demonstrate how add and remove the namespace binding assigned to the QName of an element.

A QName of an element is the optional namespace prefix and the local name. The namespace prefix and the local name are separated by a colon. The namespace prefix, if present, is bound to a URI (Universal Resource Identifier) and provides a shortened form of the URI. The expanded QName includes the namespace URI and a local name.

Using functions such as fn:QName, fn:local-name, and fn:namespace-uri you can rename attribute and node names, and find the URI associated with a node's namespace prefix.

An XQuery namespace declaration is terminated by a semicolon (;). You cannot use the semicolon as a statement termination character. The examples use the tilde (~) as the termination character, which is the same termination character used by the pureXML® tutorial.

Adding a namespace prefix to an element

The examples use an XML document from a table. The following statements create the table and inserts an XML document into the table:
CREATE TABLE XMLTEST (ID BIGINT NOT NULL PRIMARY KEY, XMLDOC XML ) ~
INSERT INTO XMLTEST Values (4, 
  '<depts>
    <dept id="A07">
        <emp id="31201" >
           <location region="31" />
        </emp>
        <emp type="new" id = "23322" >
          <moved:location xmlns:moved="http://oldcompany.com" region="43" />
        </emp>
    </dept>
    </depts> ') ~

The XQuery expression in the following SELECT statement adds a namespace prefix to an element. The XQuery expression uses fn:QName to create a QName with a namespace binding.

The XQuery let clause creates an empty element with name emp and namespace http://example.com/new. In the transform expression, the rename expression changes the name of the element identified by the XPath expression$newdept/depts/dept/emp[@type="new"]. The element is named emp but has no namespace prefix.

SELECT XMLQUERY ( ' 
  let $newemp := fn:QName( "http://mycompany.com", "new:emp")
  return
  transform
    copy $newdept := $doc
    modify
    do rename $newdept/depts/dept/emp[@type="new"] as $newemp
  return
  $newdept  ' passing XMLDOC as "doc" ) 
from XMLTEST where ID = 4 ~

The XQuery expression returns the following XML data with the namespace binding specified as part of the node new:emp. The modified document is valid XML that includes namespace prefixes that are bound to a namespace. A namespace declaration is added to the newly renamed element.

<depts>
	<dept id="A07">
		<emp id="31201">
			<location region="31" />
		</emp>
		<new:emp xmlns:new="http://mycompany.com" type="new" id="23322">
			<moved:location xmlns:moved="http://oldcompany.com" region="43" />
		</new:emp>
	</dept>
</depts>

Removing a namespace prefix from an element

You can remove a namespace prefix from a node name by renaming the node to a QName without a namespace binding. The following XQuery expression in the SELECT statement uses a for clause and the fn:namespace-uri function to determine the URI of the element nodes within each emp node. If the URI is http://oldcompany.com the rename expression uses the fn:QName and fn:local-name functions to remove the namespace prefix from the element node.

SELECT XMLQUERY ( ' 
  transform
    copy $newdept := $x
    modify
     for $testemp in $newdept/depts/dept/*:emp/*
 	   return
 	   if ( fn:namespace-uri( $testemp ) eq "http://oldcompany.com")
 	   then
       do rename $testemp as fn:QName( "", fn:local-name($testemp) )
     else()
  return
  $newdept 
 ' passing XMLDOC as "x" ) 
from XMLTEST where ID = 4 ~

The XQuery expression returns the following XML data. The node name new:location is replaced with location. The namespace binding is not removed from the node.

<depts>
  <dept id="A07">
    <emp id="31201">
      <location region="31" />
    </emp>
    <emp type="new" id="23322">
      <location xmlns:moved="http://oldcompany.com" region="43" />
    </emp>
  </dept>
</depts>