在XQuery中复制名称空间

在XQuery中复制名称空间,xquery,Xquery,我试图在旧元素的基础上构建一个新元素,包括复制它的子元素。为了防止每个子级重复作用域中每个名称空间的名称空间定义,我还对复制名称空间声明感兴趣 命名空间声明不是通过$element/@*作为常规属性获取的 如果我将代码限制为仅适用于XQuery 3.0,我可以执行以下操作: <new-element> { for $ns-prefix in in-scope-prefixes($element) let $ns-uri := namespace-uri-for-p

我试图在旧元素的基础上构建一个新元素,包括复制它的子元素。为了防止每个子级重复作用域中每个名称空间的名称空间定义,我还对复制名称空间声明感兴趣

命名空间声明不是通过
$element/@*
作为常规属性获取的

如果我将代码限制为仅适用于XQuery 3.0,我可以执行以下操作:

<new-element>
  {
    for $ns-prefix in in-scope-prefixes($element)
    let $ns-uri := namespace-uri-for-prefix($ns-prefix, $element)
    return namespace { $ns-prefix } { $ns-uri }
  }
  ...
</new-element>
<new-element>
  <child xmlns:stuff="..." name="foo"/>
  <child xmlns:stuff="..." name="bar"/>
</new-element>

{
对于作用域前缀($element)中的$ns前缀
让$ns uri:=前缀的命名空间uri($ns prefix,$element)
返回命名空间{$ns prefix}{$ns uri}
}
...
有更好的办法吗


稍微澄清一下问题--我的原始文档如下所示:

<root xmlns:stuff="...">
  <child name="foo"/>
  <child name="bar"/>
</root>

当我将子项复制到新文档中时,会得到以下结果:

<new-element>
  {
    for $ns-prefix in in-scope-prefixes($element)
    let $ns-uri := namespace-uri-for-prefix($ns-prefix, $element)
    return namespace { $ns-prefix } { $ns-uri }
  }
  ...
</new-element>
<new-element>
  <child xmlns:stuff="..." name="foo"/>
  <child xmlns:stuff="..." name="bar"/>
</new-element>


…在XQuery 3.0中,只需将
xmlns:stuff
声明附加到
就更有意义了,但如果您的实现支持名称空间轴(我认为这是一个可选特性),则以下功能应该可以工作:


{$element/名称空间::*}
...

如果允许使用XQuery Update,可以使用转换表达式(copy/modify/return)复制节点,然后修改名称。

如果使用编程构造函数,我相信它们会以您需要的方式处理名称空间声明

xquery version "1.0";

declare function local:transform($node)
{
  typeswitch($node)
  case element()
    return element { fn:node-name($node) } {
      $node/@*,
      for $n in $node/*
      return local:transform($n)
    }
  default return $node
};

let $node :=
  <dmc:root xmlns:dmc="http://davidcassel.net/dmc">
    <dmc:parent attr="value">
      <stuff:child xmlns:stuff="http://davidcassel.net/stuff">some text</stuff:child>
    </dmc:parent>
  </dmc:root>
return local:transform($node)
xquery版本“1.0”;
声明函数本地:转换($node)
{
类型开关($node)
case元素()
返回元素{fn:node name($node)}{
$node/@*,
对于$n,在$node中/*
返回本地:转换($n)
}
默认返回$node
};
让$node:=
一些文本
返回本地:转换($node)
产生

<dmc:root xmlns:dmc="http://davidcassel.net/dmc">
  <dmc:parent attr="value">
    <stuff:child xmlns:stuff="http://davidcassel.net/stuff"/>
  </dmc:parent>
</dmc:root>

向typeswitch添加事例以进行所需的结构更改。这是否实现了你的目标


使用标准XQuery 1.0在MarkLogic 5上测试

我遇到了类似的问题,只是在名称空间中的父节点上添加了一个“fake”属性,这会导致它在该级别获取声明

<new-element stuff:something="anything">
  ...

</new-element>

...

好的,XPath规范说它已被正式弃用:“从XPath 2.0开始,名称空间轴已被弃用,不需要宿主语言支持。不支持名称空间轴的宿主语言不需要以节点的形式表示名称空间绑定。”(仅在2.1标题上方几行)。顺便说一句,我的观点很遗憾。@grtjn:这是我喜欢XSLT而不喜欢XQuery的众多原因之一:)当然,@grtjn引用的内容也适用于XSLT:)您想要的是一种复制所有范围内名称空间(而不是名称空间声明)的简单方法。我个人会将您的FLWOR表达式包装为一个新函数
local:in-scope名称空间($arg as node())
反对名称空间的理由是,它使节点的实现复杂化,即使对于不使用名称空间轴的XQuery代码,也很难避免开销。对于一个很少使用的特性来说,这是一个很高的成本,因此它不包括在XQuery中。”-Per Bothner,2003()对这个问题做了一些澄清——基本上,在每个子级上定义
xmlns:stuff
是我试图避免的,当将它附加到父级的新版本时,这会更明智。