2014-01-03 4 views
1

Действительно новый для LINQ и XML. Я надеялся, что кто-то скажет мне, что я делаю неправильно, пытаясь удалить дочерний узел из XElement.Удалить дочерний узел XML из родителя с предложением where

Вот пример моего XML: (Я пытаюсь удалить «Relation», что соответствует выбранному пользователю соотношение)

<Bill> 
    <Element> 
    <Name>AccountNumber</Name> 
    <Regex></Regex> 
    <Left></Left> 
    <Right></Right> 
    <Top></Top> 
    <Bottom></Bottom> 
    <Index>0</Index> 
    <Relations></Relations> 
    </Element> 
    <Element> 
    <Name>BillDate</Name> 
    <Regex></Regex> 
    <Left></Left> 
    <Right></Right> 
    <Top></Top> 
    <Bottom></Bottom> 
    <Index>1</Index> 
    <Relations> 
     <Relation>AccountNumber.RightOf.Right.0</Relation> 
     <Relation>AccountNumber.Below.Top.-10</Relation> 
     <Relation>AccountNumber.Above.Bottom.-10</Relation> 
    </Relations> 
    </Element> 

если моему WPF GUI, когда пользователь нажимает удалить на Я хочу удалить только это отношение из родителя.

Это одна из многих вещей, которые я попробовал:

private void DeleteButton_Click(object sender, RoutedEventArgs e) 
{ 
    List<RelationsDetailView> details = (List<RelationsDetailView>)DetailsView.ItemsSource; 

    XElement parentElement = (from Node in ocrVar.Xml.Descendants("Element") 
           where Node.Element("Index").Value == ocrVar.SelectedItem.Index.ToString() 
           select Node).FirstOrDefault(); 
    XElement child = parentElement.Element("Relations").Elements("Relation").Where(xel => xel.Element("Relation").Value == (details[DetailsView.SelectedIndex].Relation)).FirstOrDefault(); 
    child.Remove(); 
    ocrVar.Xml.Save(ocrVar.xmlPath); 
} 

ответ

3

Ваш Where предикат является неверным. xel уже является элементом <relation>, поэтому вам не нужно снова звонить Element("Relation").

Вы должны также заменить XElement.Value на (string)XElement, чтобы предотвратить NullReferenceException.

.Where(xel => (string)xel == (details[DetailsView.SelectedIndex].Relation)) 

Или вы можете использовать FirstOrDefault с предикатом вместо Where().FirstOrDefault() цепи:

XElement child = parentElement.Element("Relations").Elements("Relation").FirstOrDefault(xel => (string)xel == details[DetailsView.SelectedIndex].Relation); 
+0

Отлично, спасибо, что объяснил это. Кроме того, немного советов о предотвращении исключения NullReferenceException. – Milne

+0

Добро пожаловать. Вы также можете использовать 'XElement' для' int' и изменить свое первое условие запроса на 'where (int) Node.Element (" Index ") == ocrVar.SelectedItem.Index' – MarcinJuraszek

+0

Хороший вызов. Я предполагаю, что лучше приложить что-то к int и сравнить ints, чем отличить другую как строку и сравнить две строки? Просто любопытно. – Milne

2
xel.Element("Relation").Value == (details[DetailsView.SelectedIndex].Relation 

Это условие всегда возвращает ложь, может быть, вы хотите что-то вроде этого?

(string)xel.Element("Relation") == (details[DetailsView.SelectedIndex].Relation.ToString()) 
+0

Спасибо, что указали это, Selman22. +1 – Milne

+0

Быстрый вопрос .. При вызове child.Remove() или child.RemoveNodes() он не ведет себя так, как я думал. Вместо того, чтобы удалять весь узел (AccountNumber.Below.Top.-10), вместо этого он заменяет его тем, что кажется пустым узлом (). Почему это? и есть ли способ удалить все это? Спасибо – Milne

+0

Выяснил это. – Milne

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