如何将节点从不同的命名空间复制到新文档?

How do I copy a node from different namespace to new document?

我在 MarkLogic 中有一个带有命名空间 1.Now 的 XML 文档,我想从中复制一个节点并将其粘贴到位于命名空间 2 中的另一个文档中。

我写了一个函数来从文档中获取这条数据(节点)。函数 returns 位于命名空间 1 中的文档 2 中的一个节点。

我希望此节点也与根文档位于同一名称空间中。

我可以从命名空间中删除一个节点吗?然后将其插入另一个文档? 任何其他程序来获得所需的结果?

这是我的结果,请注意根命名空间与类别元素命名空间不同...

<wijk id="1027K01" xmlns="http://www.nvsp.nl/wijk">
  <meta-data>
    <!--Generated by DIKW for NetwerkVSP STT!P -->
    <version>0.4</version>
    <dateCreated>2015-02-22+01:00</dateCreated>
  </meta-data>
  <category name="Geografie" xmlns="http://www.cendris.nl/postcode">
    <variable name="Postcode">
      <segment name="6 positie postcode">1027AA</segment>
      <segment name="5 positie postcode">1027A</segment>
      <segment name="4 positie postcode">1027</segment>
    </variable>
    <variable name="Gemeente">
      <segment name="Gemeentecode">363</segment>
      <segment name="Gemeentenaam">Amsterdam</segment>
    </variable>
    <variable name="Plaats">
      <segment name="Plaatsnaam">AMSTERDAM</segment>
    </variable>
    <variable name="Provincie">
      <segment name="Provinciecode">27</segment>
      <segment name="Provincienaam">Noord-Holland</segment>
    </variable>
    <variable name="Cebuco">
      <segment name="Cebuco naam">(21) Amsterdam-Purmerend</segment>
      <segment name="Cebuco code">21</segment>
    </variable>
    <variable name="Bible Belt">
      <segment name="nauwelijks">100</segment>
      <segment name="enigszins">0</segment>
      <segment name="redelijk sterk">0</segment>
      <segment name="sterk">0</segment>
      <segment name="zeer sterk">0</segment>
    </variable>
    <variable name="Urbanisatiegraad">
      <segment name="Zeer sterk stedelijk">100</segment>
      <segment name="Sterk stedelijk">0</segment>
      <segment name="Matig stedelijk">0</segment>
      <segment name="Weinig stedelijk">0</segment>
      <segment name="Niet stedelijk">0</segment>
    </variable>
  </category>
</wijk>

您可以通过仅使用本地名称递归地重新构造节点及其子节点来从节点中剥离命名空间。您可以使用类似的方法将节点从一个名称空间移动到另一个名称空间。

注意:从节点剥离命名空间会将节点放入 "empty" 命名空间。该节点将保留在 "empty" 命名空间中,即使它被放置为不同命名空间节点的子节点。

下面是 XQuery 中的一些命名空间操作示例:

xquery version "1.0-ml";

declare namespace html = "http://www.w3.org/1999/xhtml";
declare namespace other = "other";

declare function local:remove-namespace($x as node()) as node()?
{
  if ($x instance of element())
  then
    element { fn:local-name($x) }  {
      $x/(@*,node()) ! local:remove-namespace(.)
    }
  else $x
};

declare function local:set-namespace($x as node(), $prefix as xs:string) as node()?
{
  if ($x instance of element())
  then
    element { xs:QName($prefix || ":" || fn:local-name($x)) }  {
      $x/(@*,node()) ! local:set-namespace(., $prefix)
    }
  else $x
};

let $x := <html:p>blah, blah <html:strong>__</html:strong> blah</html:p>
return (
  $x,
  local:remove-namespace($x),
  local:set-namespace($x, "other")
)

按以下顺序评估该示例结果:

<html:p xmlns:html="http://www.w3.org/1999/xhtml">blah, blah <html:strong>__</html:strong> blah</html:p>,
<p>blah, blah <strong>__</strong> blah</p>,
<other:p xmlns:other="other">blah, blah <other:strong>__</other:strong> blah</other:p>

命名空间节点并不是 XQuery 数据模型中真正的第一个 class 公民。 XQuery 工作组显然认为我们不应该被允许操纵它们。但是还是有一些技巧的。

这是一个例子,用 8.0-1.1 测试过:

declare function local:do(
  $n as node(), $ns as xs:string)
as node()
{
  typeswitch($n)
  case document-node() return document { local:do($n/node(), $ns) }
  case element() return element { QName($ns, local-name($n)) } {
    $ns,
    $n/@*,
    local:do($n/node(), $ns) }
  default return $n
};

<test xmlns="a">
  <fubar><baz/></fubar>
</test>
! local:do(., "b")

一旦您的 XML 元素具有所需的命名空间,您就可以像往常一样操作它们:xdmp:node-insert-child for example, or one of the libraries for in-memory update: https://github.com/ryanjdew/XQuery-XML-Memory-Operations

另一个有用的名称空间技巧涉及 XPath namespace 轴。如果您有嘈杂的命名空间声明,这也会有所帮助。

<test xmlns="a">
  <b:fubar xmlns:b="b"><baz/></b:fubar>
  <b:fubar xmlns:b="b"><buz/></b:fubar>
</test>
! element { node-name(.) } {
  node()/namespace::*,
  @*,
  node() }

这具有将 xmlns:b 声明提升到根元素级别的效果。

最后,有时您可以使用具有默认命名空间选项的 xdmp:quotexdmp:unquote 来做一些小技巧。

有一个简单的方法:使用 functx:change-element-ns-deep 函数。 functx 库随 MarkLogic 一起分发。导入它们,使用“”作为新的命名空间调用该函数,然后就可以了。