【问题标题】:How to Replace multiple nodes of XML efficiently?如何有效地替换 XML 的多个节点?
【发布时间】:2018-09-06 09:40:57
【问题描述】:

我试图一次替换大约 500 个节点以获取单个文档,并且我的数据库中有 5000 多个文档。

我正在使用的代码与我之前提出的这个 SO 问题有关- Link

有什么建议可以让我的代码高效吗?

【问题讨论】:

    标签: xquery marklogic


    【解决方案1】:

    通常应避免使用 in-mem-update 库,尤其是在对同一文档进行大量方法调用时。由于每个方法都会遍历整个节点树并生成一个全新的文档,因此如果您针对大型文档运行和/或对这些文档进行大量 mem:* 方法调用,它可能会很慢而且成本很高。

    更好的替代品是 Ryan Dew 的 XQuery XML Memory Operations library,或者使用 XSLT。

    下面是一个示例,说明如何使用 XSLT 执行这种“合并”,它应该比 in-mem-update 方法执行得更好:

    declare variable $STAGING := document{
    <root>
     <ID>1</ID>
     <value1>India</value1>
     <value2>USA</value2>
     <value3>Russia</value3>
     <value4>Srilanka</value4>
     <value5>Europe</value5>
     <value6>Antartica</value6>
     <value7>Spain</value7>
    </root>
    };
    
    declare variable $FINAL := document{
    <root>
     <ID>1</ID>
     <value1></value1>
     <value2></value2>
     <value3></value3>
     <value4></value4>
     <value5>Europe</value5>
     <value6>Antartica</value6>
    </root>
    };
    
    declare variable $XSLT := 
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    
      <xsl:param name="staging-doc"/>
      <xsl:param name="element-names"/>
    
      <xsl:variable name="final-doc" select="/"/>
    
      <xsl:key name="staging-elements" match="root/*[local-name() = $element-names]" use="local-name()"/>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="root/*[local-name() = $element-names]">
        <!--if there is an element in the staging-elements doc with this name, use it. Otherwise, use the matched element from this doc -->
        <xsl:copy-of select="(key('staging-elements', local-name(.), $staging-doc), .)[1]"/>
      </xsl:template>
    
      <xsl:template match="root">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
          <!-- also copy any other elements with the specified names from the staging document that were not already in the final -->
          <xsl:apply-templates select="$staging-doc/root/*[local-name() = $element-names and not(key('staging-elements', local-name(), $final-doc))]"/>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>;
    
    declare variable $PARAMS := map:new((
        map:entry("staging-doc", $STAGING), 
        map:entry("element-names", tokenize(("value1,value2,value3,value4,value7"), ",") )
      ));
    
    xdmp:xslt-eval($XSLT, $FINAL, $PARAMS)
    

    【讨论】:

    • @Mads-- 非常感谢。它也需要xdmp:document-insert () 吗?或者它会自动将所有文档替换到数据库中?
    • 是的,您需要保存结果(在代码部分中使用,您在 if ($boolean) then 中有条件地设置 $envelope,而不是使用 in-mem 函数)
    • @Mads-- 非常感谢 :) 这很有帮助。
    猜你喜欢
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-11
    • 2014-08-27
    • 2013-07-13
    相关资源
    最近更新 更多