【问题标题】:How do I copy a node from different namespace to new document?如何将节点从不同的命名空间复制到新文档?
【发布时间】:2015-02-23 21:00:54
【问题描述】:

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

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

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

我可以从它的命名空间中剥离一个节点吗?然后将其插入另一个文档中? 还有什么其他的程序可以得到想要的结果吗?

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

<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>

【问题讨论】:

    标签: xquery marklogic


    【解决方案1】:

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

    【讨论】:

    • 您可以使用此导入行:import module namespace functx = "http://www.functx.com" at "/MarkLogic/functx/functx-1.0-nodoc-2007-01.xqy";。在 ML8 中也应该像这样工作..
    【解决方案2】:

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

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

    这是 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>
    

    【讨论】:

      【解决方案3】:

      命名空间节点在 XQuery 数据模型中并不是真正的一等公民。 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,或用于内存更新的库之一: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 来做一些技巧,它们有一个默认的命名空间选项。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-24
        • 2014-09-08
        • 1970-01-01
        • 2013-05-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多