XmlNode clone () очень медленно в запросах XPath в XML - PullRequest
1 голос
/ 14 ноября 2010

У меня есть требование, где есть большой XML-документ.Я должен выбрать много узлов, использующих XPath из документа, основываясь на некоторых условиях.Затем после того, как я выбрал XmlNodes, мне нужно добавить новые свойства в выбранные узлы и вставить его во многие места в XmlDocument.

Я обнаружил, что когда я изменяю выбранный XmlNode, фактический XmlDocument такжемодифицирована. Поэтому я подумал об использовании метода xmlNode.Clone () во всем списке выбранных XmlNodes . Но это действительно очень, очень медленно .Я имею в виду, есть ли лучший способ сделать это?Или клон действительно очень медленный ??
Кстати, я использую XmlDocument для загрузки документа Xml.

Редактирует ЗДЕСЬ :::

Я добавляю больше деталей к своему вопросу.Я использую язык C # и .net 3.5 в качестве платформы.

Я связал этот Xml с сеткой данных и позволил пользователю изменять сетку данных.Исходя из некоторых условий, когда пользователь изменяет ячейку в сетке данных, мне нужно выбрать некоторые узлы в Xml, а затем создать новые узлы и добавить их в XmlDocument, который находится в памяти.Поэтому после выбора объектов я использовал clone (), что очень медленно для меня !!

Больше правок ЗДЕСЬ ::

Исходный XML выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<grids>   
    <row>
       <value actualvalue="test1" id="0001" valuetype="Constant"/> // i want to make copy of this node whose id = 0001 and make some changes to it
    <value actualvalue="test2" id="0002" valuetype="String"/>
   </row>  
</grids>



Затем я хочу изменить узел, и преобразованный XML должен выглядеть следующим образом: Новый узел был добавлен и идентификаторы были переупорядочены.

<?xml version="1.0" encoding="UTF-8"?>
<grids>   
    <row>
       <value actualvalue="test1" id="0001" valuetype="newConstant"/> 
       <value actualvalue="test1" id="0002" valuetype="Constant"/> 
    <value actualvalue="test2" id="0003" valuetype="String"/>
   </row>  
</grids>

Надеюсь, мои данныедостаточно !!

Ответы [ 4 ]

2 голосов
/ 15 ноября 2010

Я подозреваю, что виновник здесь таков:

Я связал этот Xml с сеткой данных и позволил пользователю изменять сетку данных.

Связывание данных снижает производительность. Когда объект привязан к пользовательскому интерфейсу, все изменения этого объекта динамически отражаются в изменениях пользовательского интерфейса. Если вы вносите много обновлений в объект, и каждое из этих изменений распространяется в пользовательском интерфейсе по мере их создания, вы вставляете вычислительную стоимость переформатирования и визуализации компонентов пользовательского интерфейса в середину обновления XML.

Если вы отключите привязку, выполните обновление, а затем снова включите привязку после того, как обновление выполнено, вполне вероятно, что описываемые вами проблемы с производительностью уменьшатся до незначительности.

2 голосов
/ 15 ноября 2010

Другое решение XSLT с «мелкозернистым обходом»:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:param name="pSearchId" select="1"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:param name="pIdIncrement" select="0"/>
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*">
                <xsl:with-param name="pIdIncrement" select="$pIdIncrement"/>
            </xsl:apply-templates>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]">
            <xsl:with-param name="pIdIncrement" select="$pIdIncrement"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="value">
        <xsl:param name="pIdIncrement"/>
        <xsl:if test="@id = $pSearchId">
            <value actualvalue="{@actualvalue}" 
                   id="{@id}" 
                   valuetype="new{@valuetype}"/>
        </xsl:if>
        <xsl:call-template name="identity">
            <xsl:with-param name="pIdIncrement" 
                            select="$pIdIncrement + (@id = $pSearchId)"/>
        </xsl:call-template>
    </xsl:template>
    <xsl:template match="value/@id">
        <xsl:param name="pIdIncrement"/>
        <xsl:attribute name="id">
            <xsl:value-of select="format-number(.+$pIdIncrement,'0000')"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Выход:

<grids>
    <row>
        <value actualvalue="test1" id="0001" valuetype="newConstant"/>
        <value actualvalue="test1" id="0002" valuetype="Constant"/> // i want to make copy of this node whose id = 0001 and make some changes to it
        <value actualvalue="test2" id="0003" valuetype="String"/>
    </row>
</grids>
1 голос
/ 14 ноября 2010

Это преобразование:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pinsertBefore" select="1"/>
 <xsl:param name="pnewActualvalue" select="'test1'"/>
 <xsl:param name="pnewValueType"
      select="'newConstant'"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="value">
  <xsl:choose>
   <xsl:when test=
    "(not(@id >= $pinsertBefore)
    and
      not(following-sibling::value[1]/@id = $pinsertBefore)
      )
    ">
    <xsl:call-template name="identity"/>
   </xsl:when>

   <xsl:when test=
    "not(@id >= $pinsertBefore)
    and
     following-sibling::value[1]/@id = $pinsertBefore
    ">
     <xsl:call-template name="identity"/>

     <value actualvalue="{$pnewActualvalue}"
            id="{$pinsertBefore}"
            valuetype="{$pnewValueType}"/>
   </xsl:when>

   <xsl:when test=
    "@id = $pinsertBefore
    and
     not(preceding-sibling::value[1])
    ">
     <value actualvalue="{$pnewActualvalue}"
            id="{$pinsertBefore}"
            valuetype="{$pnewValueType}"/>

     <xsl:apply-templates select="." mode="increment"/>
   </xsl:when>
   <xsl:otherwise>
     <xsl:apply-templates select="." mode="increment"/>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="node()|@*" mode="increment">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*" mode="increment"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="value/@id" mode="increment">
  <xsl:attribute name="id">
    <xsl:value-of select=". +1"/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<grids>
    <row>
       <value actualvalue="test1" id="0001"
       valuetype="Constant"/>
       <!-- i want to make copy of this node
       whose id = 0001 and make some changes to it
       -->
    <value actualvalue="test2" id="0002"
           valuetype="String"/>
   </row>
</grids>

создает искомый, правильный результат :

<grids>
   <row>
      <value actualvalue="test1" id="1" valuetype="newConstant"/>
      <value actualvalue="test1" id="2" valuetype="Constant"/><!-- i want to make copy of this node
       whose id = 0001 and make some changes to it
       -->
      <value actualvalue="test2" id="3" valuetype="String"/>
   </row>
</grids>

Примечание :

  1. идентификатор шаблон копирует каждый узел "как есть".

  2. Соответствующий шаблон value различает четыре случая , в одном из которых узел копируется как есть,в другом узел копируется, и его атрибут id увеличивается, а в двух случаях копируется узел (с увеличением или без увеличения его атрибута id), и создается новый элемент value.

0 голосов
/ 14 ноября 2010

Я не уверен, что вопрос имеет отношение к XPath, если проблема заключается в методе Clone.Пожалуйста, сначала скажите нам, какой язык и платформу вы используете.Я подозреваю из XmlNode и XmlDocument, что вы используете .NET Framework, но вы на самом деле не сказали нам.Что касается альтернатив, изменение / преобразование / вставка узлов также может быть выполнено с помощью XSLT (хотя вы не вносите изменения в существующий объект таким образом, вы создаете новый результат).Работает ли это лучше, я не знаю, вам нужно измерить это, чтобы точно знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...