1
votes

I'm trying to dynamically create some new nodes in an xml document based on the nodes around it. The issue I am having is that I want to add a new node after stock that has the same namespace as stock. While it would be easy for this example, I want to be able to do it without knowing the namespaces around me. Is it possible to copy and then rename a node so that I can preserve its namespace and possibly other attributes?

i.e. if I had

<?xml version="1.0" encoding="UTF-8"?>
<nsX:bookstore xmlns:nsX="http://namespace1" xmlns:nsY="http://namespace2">
  <nsX:bookList>
    <nsX:book category="COOKING">
      <nsX:title lang="en">Everyday Italian</nsX:title>
      <nsY:stock>1</nsY:stock>
    </nsX:book>
    <nsX:book category="CHILDREN">
      <nsX:title lang="en">Harry Potter</nsX:title>
      <nsY:stock>0</nsY:stock>
    </nsX:book>
    <nsX:book category="WEB">
      <nsX:title lang="en">XQuery Kick Start</nsX:title>
      <nsY:stock>1</nsY:stock>
    </nsX:book>
    <nsX:book category="WEB">
      <nsX:title lang="en">Learning XML</nsX:title>
      <nsY:stock>0</nsY:stock>
    </nsX:book>
  </nsX:bookList>
</nsX:bookstore>

and wanted to generate the following without already knowing what namespaces were present.

<?xml version="1.0" encoding="UTF-8"?>
<nsX:bookstore xmlns:nsX="http://namespace1" xmlns:nsY="http://namespace2">
  <nsX:bookList>
    <nsX:book category="COOKING">
      <nsX:title lang="en">Everyday Italian</nsX:title>
      <nsY:stock>1</nsY:stock>
      <nsY:newNode></nsY:newNode>
    </nsX:book>
    <nsX:book category="CHILDREN">
      <nsX:title lang="en">Harry Potter</nsX:title>
      <nsY:stock>0</nsY:stock>
      <nsY:newNode></nsY:newNode>
    </nsX:book>
    <nsX:book category="WEB">
      <nsX:title lang="en">XQuery Kick Start</nsX:title>
      <nsY:stock>1</nsY:stock>
      <nsY:newNode></nsY:newNode>
    </nsX:book>
    <nsX:book category="WEB">
      <nsX:title lang="en">Learning XML</nsX:title>
      <nsY:stock>0</nsY:stock>
      <nsY:newNode></nsY:newNode>
    </nsX:book>
  </nsX:bookList>
</nsX:bookstore>

Currently I create the new node using xQuery with my BaseXDB

insert node <newNode></newNode> after $v/*:bookList/*:book/*:stock

(where $v is bookstore)

How do I detect the namespace of the stock node and then apply it to the new nodes I am making?

1

1 Answers

4
votes

Use fn:namespace-uri() to get the namespace URI of a node, then, create a QName from a URI and a local-name with fn:QName(). Finally, create an element from a QName using the element constructor:

let $ns-uri := ($v/*:bookList/*:book/*:stock)[1]/fn:namespace-uri(.)
let $new-node := element { fn:QName($ns-uri, "newNode") } {}
return
  insert node $new-node after $v/*:bookList/*:book/*:stock