views:

91

answers:

2
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?

+3  A: 

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.)

Jon Skeet
omg. this worked..Do you work for microsoft or something. I am now aware I have alot to learn about linq itself. Thank you -- May i ask which books do you read to learn about linq to xml?
Luke101
@Luke101: No, I don't work for MS. I work for Google :) As for reading books... I wrote about LINQ in C# in Depth, so I taught myself with the docs at the time, mostly.
Jon Skeet
A: 

Guys i have a XML file like this.

    <?xml version="1.0" encoding="utf-8" ?> 
<confsistemas_fs>
      <equipe_inst>
            <tecservico>
                  <tec sigla='TEC001' nome='FULANO DA SILVA'/>
                  <tec sigla='TEC002' nome='FULANO DA SILVA'/>
                  <tec sigla='TEC003' nome='FULANO DA SILVA'/>
                  <tec sigla='TEC004' nome='FULANO DA SILVA'/>
                  <tec sigla='TEC005' nome='FULANO DA SILVA'/>
                  <tec sigla='TEC006' nome='FULANO DA SILVA'/>
            </tecservico>
      </equipe_inst>
      <eventos>
            <anormalidade>
                  <an sigla='AM010' nome='CP - MODEM INOPERANTE'/>
            </anormalidade>
            <atuacoes>
                  <at sigla='AT009' nome='CP - POLLING FORCADO'/>
            </atuacoes>
            <inf_adicional>
                  <ia sigla='IA001' nome='CABO ROMPIDO'/>
            </inf_adicional>
      </eventos>
      <relacaotc>
            <relacoes>
                  <rel_tc sigla='REL_TC1' nome='0001/01'/>
            </relacoes>
      </relacaotc>
</confsistemas_fs>

And i can't read the tecservico element using xDocument.Descendants();

Can you help me?

willian