Luke101
Luke101

Reputation: 65308

Why is this Linq to XML query not working

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

Answers (1)

Jon Skeet
Jon Skeet

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

Related Questions