Как эффективно заменить несколько узлов XML? - PullRequest
0 голосов
/ 06 сентября 2018

Я пытаюсь заменить около 500 узлов за один раз для одного документа, и у меня есть 5000+ документов в моей базе данных.

Код, который я использую, связан с этим SO вопросом, который я задавал ранее. Ссылка

Какие-нибудь предложения, чтобы сделать мой код эффективным?

1 Ответ

0 голосов
/ 07 сентября 2018

Следует избегать использования библиотеки in-mem-update, особенно при выполнении многочисленных вызовов методов для одного и того же документа. Поскольку каждый метод проходит по всему дереву узлов и генерирует новый документ, он может быть медленным и дорогостоящим, если вы работаете с большими документами и / или делаете несколько вызовов метода mem: * для этих документов.

Лучшей заменой была бы Библиотека операций с памятью XQuery XML Райана Дью или использование 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)
...