Есть ли способ создать итератор Linq XElement, который обновляется по мере изменения дерева? - PullRequest
3 голосов
/ 19 января 2009

Я новичок в C # и Linq. Я пытаюсь использовать коллекцию элементов, сгенерированную Linq, для итерации и изменения определенных элементов в XDocument. Насколько я понимаю, перечисление не обновляется при обновлении дерева.

Например, с учетом документа

<root xmlns:ns="http://dummy">
<ns:a/>
<ns:b/>
<c/>
<ns:a><ns:a/></ns:a>
</root>

и код

XDocument doc = XDocument.Load(@"test_input.xml", LoadOptions.PreserveWhitespace);
XNamespace ns = "http://dummy";

IEnumerable<XElement> elem_list = from elem in doc.Descendants()
                                  where elem.Name.Namespace == ns
                                  select elem;

foreach (XElement elem in elem_list) {
   if (elem.Name.LocalName == "a") {
      elem.Remove();
   }
}

выдает ошибку, потому что (я думаю) вложенный элемент "a" удален из дерева, но все еще "присутствует" в elem_list.

Как мне обойти это, имея в виду, что (1) реальные манипуляции, которые я хочу сделать, включают более сложные операции (например, копирование) над деревом, чем в приведенном выше примере, и (2) я работаю со смешанным контентом со значительным пробелом? Есть ли у одного из других классов документов .Net XML способ перебора, который обновляется при изменении дерева?

1 Ответ

2 голосов
/ 19 января 2009

Обычно перечислители не могут продолжать работу после изменения коллекции. Однако, если вы используете ToArray() или ToList() для них, весь набор результатов будет находиться в статическом списке. Затем вы можете перечислить их по списку, и удаление их (из документа, а не из списка) не будет иметь значения.

XDocument doc = XDocument.Load(@"test_input.xml", LoadOptions.PreserveWhitespace);
XNamespace ns = "http://dummy";

IEnumerable<XElement> elem_list = from elem in doc.Descendants()
                                  where elem.Name.Namespace == ns
                                  select elem;

XElement[] elem_array = elem_list.ToArray();

foreach (XElement elem in elem_array) {
   if (elem.Name.LocalName == "a") {
      elem.Remove();
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...