2010-07-09 2 views
8

Это удаляет все элементы из документа:Удаление узлов из XDocument

 XDocument document = XDocument.Load(inputFile); 
     foreach (XElement element in document.Elements()) 
     { 
      element.Remove(); 
     } 
     document.Save(outputFile); 

Это не имеет никакого эффекта:

 XDocument document = XDocument.Load(inputFile); 
     foreach (XElement element in document.Elements()) 
     { 
      //element.Remove(); 
      foreach (XElement child in element.Elements()) 
       child.Remove(); 
     } 
     document.Save(outputFile); 

Я пропускаю что-то здесь? Так как это все ссылки на элементы в XDocument, не должны ли изменения вступать в силу? Есть ли другой способ, которым я должен удалять вложенные дети из XDocument?

Спасибо!

+0

Вы отлажена код? Вы уверены, что element.Elements() возвращает дочерние элементы? Просто ищите немного больше информации о том, что именно вы видите. – jrista

+0

@jrista Возвращает дочерние элементы, но проблема, похоже, связана с переходом счетчика по-разному после '.Remove()'. – Jake

+1

Да, это то, чего я ожидал бы. Перечислители обычно генерируют исключения при изменении коллекции, так как они очень зависят от стабильности базовой коллекции для правильной работы. Я действительно удивлен, что вы можете продолжить работу после удаления узла при использовании foreach/enumerator. Обычно я рекомендую использовать цикл while (или, возможно, для ... но это сложнее), а не foreach. – jrista

ответ

18

Очевидно, когда вы перебирать element.Elements(), вызывая Remove() на одной из причин детей перечислитель до yield break. Исправлена ​​ошибка element.Elements().ToList().

+0

Является ли это специфическим для XPath? – Neo

+0

@Neo Каким образом? Как указывалось выше [jirsta] (http://stackoverflow.com/users/111554/jrista), большинство счетчиков будет ломаться, когда базовая коллекция изменится. – Jake

+0

Да, я знаю, что исключение InvalidOperationException происходит нормально. Мой вопрос о «уступке дохода». Является ли это специфическим для комментария XPath vis-à-vis @ jrista за молчание? – Neo

2

Вот пример другого способа с использованием System.Xml.XPath (изменить запрос XPATH в соответствии с вашими потребностями):

const string xml = 
    @"<xml> 
     <country> 
      <states> 
       <state>arkansas</state> 
       <state>california</state> 
       <state>virginia</state> 
      </states> 
     </country> 
    </xml>"; 
XDocument doc = XDocument.Parse(xml); 
doc.XPathSelectElements("//xml/country/states/state[.='arkansas']").ToList() 
    .ForEach(el => el.Remove());; 
Console.WriteLine(doc.ToString()); 
Console.ReadKey(true); 
2

При использовании XDocument попробуйте вместо этого:

XDocument document = XDocument.Load(inputFile); 
foreach (XElement element in document.Elements()) 
{ 
    document.Element("Root").SetElementValue(element , null); 
} 
document.Save(outputFile) 

С уважением, Тодд

Смежные вопросы