Reputation: 65308
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
XDocument xDocument = new XDocument(
new XElement("BookParticipants",
new XElement("BookParticipant",
new XAttribute("type", "Author"),
new XElement("FirstName", "Joe", new XElement("name",
new XElement("noot", "the"),
new XElement("iscool", "yes"))),
new XElement("LastName", "Rattz")),
new XElement("BookParticipant",
new XAttribute("type", "Editor"),
new XElement("FirstName", "Ewan", new XElement("name",
new XElement("noot", "the"),
new XElement("iscool", "yes"))),
new XElement("LastName", "Buckingham"))));
xDocument.Descendants("BookParticipants").Where(x => (string)x.Element("FirstName") == "Joe").Remove();
Console.WriteLine(xDocument);
}
}
}
I am trying to remove the joe element using the where clause. But this is not working. is it possible to delete elements using the where clause?
Upvotes: 2
Views: 623
Reputation: 1503944
EDIT: Hmm... I wasn't aware of that Remove
extension method before.
The problem is that when you convert an element into a string, it concatenates all the descendant text nodes... so the value of the "Joe" element is actually "Joe the yet".
You only want direct child text nodes. Frankly it would be easier if the name was in an attribute rather than as content, but it should still be feasible...
Additionally, you're looking for FirstName
elements directly under BookParticipants
rather than BookParticipant
.
This works, although it's not terribly pleasant:
xDocument.Descendants("BookParticipants")
.Elements()
.Where(x => x.Elements("FirstName")
.Nodes()
.OfType<XText>()
.Any(t => t.Value== "Joe"))
.Remove();
You could change the first bit to
xDocument.Descendants("BookParticipant")
.Where(...)
if you want, too.
(Again, if you can use attributes for string values rather than content in elements, that makes life easier.)
Upvotes: 3