Операция Remove

82

Операция Remove может быть вызвана на последовательности узлов или атрибутов для их удаления. Этот метод кэширует копию узлов или атрибутов в List для того, чтобы избежать "проблемы Хэллоуина".

Операция Remove имеет два прототипа, описанные ниже:

Первый прототип Remove
public static void Remove ( 
         this IEnumerable<XAttribute> source)

Эта версия вызывается на последовательности атрибутов и удаляет все атрибуты в исходной последовательности.

Второй прототип Remove
public static void Remove<T> (
   this IEnumerable<T> source 
   ) where T : XNode

Эта версия вызывается на последовательности указанного типа, элементы которой должны быть узлами или типом, производным от узлов, и удаляет все узлы входной последовательности.

Поскольку первый прототип предназначен для удаления атрибутов, понадобилась последовательность атрибутов. Поэтому будет построено стандартное дерево XML и извлечена последовательность атрибутов элементов Employee. Сначала последовательность исходных атрибутов отображается, после чего на ней вызывается операция Remove. Затем для доказательства работоспособности отображается весь XML-документ с удаленными атрибутами:

XDocument xDoc = new XDocument(
             new XElement("Employees",
               new XComment("Список сотрудников"),
               new XElement("Employee",
                 new XAttribute("type", "Programmer"),
                 new XComment("Это программист"),
                 new XElement("FirstName", "Alex"), 
                 new XElement("LastName", "Erohin")),
               new XElement("Employee",
                 new XAttribute("type", "Editor"),
                 new XElement("FirstName", "Elena"), 
                 new XElement("LastName", "Volkova"))));

            IEnumerable attributes =
                  xDoc.Element("Employees").Elements("Employee").Attributes();

            //  Сначала отобразим все исходные атрибуты
            foreach (XAttribute attr in attributes)
            {
                Console.WriteLine("Исходный атрибут: {0} : значение = {1}", attr.Name, attr.Value);
            }

            Console.WriteLine("\n\nXML-разметка после удаления атрибутов: \n");

            //  Теперь удалим атрибуты и отобразим документ
            attributes.Remove();

            Console.WriteLine(xDoc);

Будет ли это работать? Давайте посмотрим:

Вызов первого прототипа Remove

Пока все хорошо. Теперь попробуем применить второй прототип. Для этого примера вместо получения последовательности узлов и удаления их будет продемонстрировано нечто более интересное. Будет построена последовательность комментариев определенных элементов, и только эти комментарии будут удалены:

XDocument xDoc = new XDocument(
             new XElement("Employees",
               new XElement("Employee",
                 new XAttribute("type", "Programmer"),
                 new XComment("Это программист"),
                 new XElement("FirstName", "Alex"), 
                 new XElement("LastName", "Erohin")),
               new XElement("Employee",
                 new XAttribute("type", "Editor"),
                 new XElement("FirstName", "Elena"), 
                 new XElement("LastName", "Volkova"))));

            IEnumerable<XComment> comments =
                  xDoc.Element("Employees").Elements("Employee").Nodes().OfType<XComment>();

            //  Сначала отобразим все исходные комментарии
            foreach (XComment com in comments)
            {
                Console.WriteLine("Исходный комментарий: " + com);
            }

            Console.WriteLine("\n\nXML-разметка после удаления комментария: \n");

            //  Теперь удалим комментарий и отобразим документ
            comments.Remove();

            Console.WriteLine(xDoc);

В данном примере при построении исходной последовательности извлекаются дочерние узлы каждого элемента Employee. Можно было бы просто вызвать операцию Remove на этой последовательности, и тогда все дочерние узлы каждого элемента Employee исчезли бы. Но вместо этого вызывается стандартная операция запроса OfType. Эта операция вернет только те объекты входной последовательности, которые соответствуют указанному типу. Вызывая операцию OfType и указывая тип XComment, получается последовательность, состоящая только из комментариев — comments. Затем на comments вызывается метод Remove. В результате исходный документ будет очищен от всех комментариев:

Вызов второго прототипа Remove

Код работает весьма неплохо. Оцените, насколько удобна операция OfType, и как она интегрируется в запрос LINQ to XML. Похоже, она может оказаться весьма полезной во многих ситуациях.

Пройди тесты
Лучший чат для C# программистов