I'm trying to remove an item with xml to linq but I can't get it to work:
<books>
<book>
<title>Harry Potter und der Stein der Waisen</title>
<isbn>1</isbn>
<author>J. K. Rowling</author>
<price>30</price>
</book>
</books>
I'm trying to navigate to the specific element and then call .Remove()
public void DeleteItem(Book toRemove)
{
var xmlDoc = this.xmlFileStorage.LoadXmlDocument();
xmlDoc
.Descendants("books")
.Elements("book")
.Where(x =>
x.Elements("title").Single(y => y.Value == toRemove.Title)
&& x.Elements("author").Single(y => y.Value == toRemove.Author)
&& x.Elements("isbn").Single(y => y.Value == toRemove.Isbn)
&& x.Elements("price").Where(y => y.Value == toRemove.Price.ToString()))
.Remove();
this.xmlFileStorage.SaveXmlDocument(xmlDoc);
}
I don't think the .Single()
is the right approach...
how can I get the exact record from the xml Document?
Thanks in advance
I would suggest using Element
instead of Elements
, and casting the XElement
to string
instead of using Value
. Combine that with using Title
instead of title
and it should be fine:
xmlDoc.Descendants("books")
.Elements("book")
.Where(x => (string) x.Element("title") == toRemove.Title
&& (string) x.Element("author") == toRemove.Author
&& (string) x.Element("isbn") == toRemove.Isbn
&& (string) x.Element("price") == toRemove.Price)
.Remove();
This will remove all matching elements, of course. If you want to ensure that there's only one match, you could call SingleOrDefault()
, check that the result isn't null, and then call Remove
on the XElement
.
Another option to consider is just matching on ISBN - that's effectively the identifier for the book, isn't it? If your book happens to have a different price, or the author has different punctuation, do you definitely want that to prevent the removal?
See more on this question at Stackoverflow