Удалить / удалить узел из XPathNodeIterator, учитывая XPath - PullRequest
0 голосов
/ 26 марта 2010

Прежде всего, если у кого-то есть другое, возможно, более короткое (или лучшее) решение проблемы, это тоже приветствуется.


Я пытаюсь «просто» удалить (почти) дублировать элементы в XSLT.Есть некоторые (метаданные) узлы, которые я не хочу включать при сравнении, и я не мог понять, как это сделать в XSLT, поэтому подумал, что я бы расширил его с помощью функции, удаляющей эти узлы.Примерно так:

<xsl:for-each select="abx:removeNodes(d/df600|d/df610|d/df611|d/df630|d/df650|d/df651|d/df655, '*[@key=&quot;i1&quot; or @key=&quot;i2&quot; or key=&quot;db&quot;]')">
   <xsl:if test="not(node()=preceding-sibling::*)">
      blah
   </xsl:if>
</xsl:for-each>

И расширение, которое работает не так хорошо ... (C #)

public XPathNodeIterator removeNodes(XPathNodeIterator p_NodeIterator, String removeXPath)
{
   Logger Logger = new Logger("xslt");
   Logger.Log("removeNodes(removeXPath={0}):", removeXPath);

   foreach (XPathNavigator CurrentNode in p_NodeIterator)
   {
      Logger.Log("removeNodes(): CurrentNode.OuterXml={0}.", CurrentNode.OuterXml);

      foreach (XPathNavigator CurrentSubNode in CurrentNode.Select(removeXPath))
      {
         Logger.Log("removeNodes(): CurrentSubNode.OuterXml={0}.", CurrentSubNode.OuterXml);
         // How do i delete this node!?
         //CurrentSubNode.DeleteSelf();
      }
   }

   return p_NodeIterator;
}

Мой первоначальный подход с использованием CurrentSubNode.DeleteSelf (); 'не работает, потому что он запутывается и теряет свою позицию в XPathNavigator, в результате чего он удаляет только первый найденный элемент, используя «removeXPath».Было бы неплохо что-то вроде DeleteAndMoveNext (), но, похоже, такого метода нет ...


Пример данных:

<df650>
  <df650 key="i1"> </df650>
  <df650 key="i2">0</df650>
  <df650 key="a">foo</df650>
  <df650 key="x">bar</df650>
  <df650 key="db">someDB</df650>
  <df650 key="id">b2</df650>
  <df650 key="dsname">someDS</df650>
</df650>

.. а затем еще один идентичный узел (есливы игнорируете мета-поля; db, id, dsname).

<df650>
  <df650 key="i1"> </df650>
  <df650 key="i2">0</df650>
  <df650 key="a">foo</df650>
  <df650 key="x">bar</df650>
  <df650 key="db">someOtherDB</df650>
  <df650 key="id">b2</df650>
  <df650 key="dsname">someOtherDS</df650>
</df650>

Результат должен быть ...

<df650>
  <df650 key="i1"> </df650>
  <df650 key="i2">0</df650>
  <df650 key="a">foo</df650>
  <df650 key="x">bar</df650>
</df650>

Ответы [ 3 ]

1 голос
/ 02 июня 2010

Спасибо за подсказку RymdPung, я смог удалить пустые строки в повторяющемся разделе, используя ваше предложение List.

Я добавил ссылку на пространство имен System.Collections.Generic в своем коде.

Вот метод, который я создал, чтобы сканировать через набор узлов, определить те, которые я хочу удалить, а затем удалить их в отдельном цикле.

         private void deleteEmptyRows(string path)
    {
        XPathNodeIterator nodesToCheck = MainDataSource.CreateNavigator().Select(path, NamespaceManager);
        List<XPathNavigator> nodesToDelete = new List<XPathNavigator>();
        foreach (XPathNavigator currentItem in nodesToCheck)
            if (currentItem.Value.Trim().Length == 0)
                nodesToDelete.Add(currentItem);

        foreach(XPathNavigator deleteMe in nodesToDelete)
            deleteMe.DeleteSelf();
    }
1 голос
/ 29 марта 2010

Вы можете легко сделать это только в XSLT, функция расширения действительно не нужна. Учтите это:

<!-- make a template that matches all nodes that cold be removed -->
<xsl:template match="d/df600|d/df610|d/df611|d/df630|d/df650|d/df651|d/df655">
  <!-- check the your condition for node removal, whatever it may be -->
  <xsl:if test="not(@key='i1' or @key='i2' or @key='db')">
    <!-- ...if it is *not* met, copy the node -->
    <xsl:copy-of select="." />
  </xsl:if>
  <!-- ...in all other cases, nothing happens, i.e. the node is removed -->
</xsl:template>
0 голосов
/ 30 марта 2010

Проблема может быть решена следующим образом (однако, она не решает МОЮ актуальную проблему ...).

  • Создайте список типа XPathNavigator, который будет содержать узлы, которые вы хотите удалить.
  • Добавить узлы в этот список вместо использования DeleteSelf ().
  • Когда вы найдете все узлы, которые хотите удалить, выполните итерацию в вашем Списке и удалите узлы. Поскольку эти узлы являются навигаторами, нет проблем с потерянной позицией.

Я перестал пытаться вставить код через 10 минут ...

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