Операции DescendantNodes и DescendantNodesAndSelf

52

DescendantNodes

Операция DescendantNodes может быть вызвана на последовательности элементов и возвращает последовательность, содержащую узлы-наследники каждого элемента в документе.

Операция DescendantNodes имеет один прототип, который описан ниже:

public static IEnumerable<XNode> DescendantNodes<T> (
   this IEnumerable<T> source 
   ) where T : XContainer

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

Отличие от метода XContainer.DescendantNodes заключается в том, что этот метод вызывается на последовательности элементов или документов, а не на одном элементе или документе.

Для примера построим то же самое дерево XML, что и в предыдущих статьях за исключением того, что также будет добавлен комментарий к первому элементу Employee. Это нужно для того, чтобы как минимум один возвращенный узел не был элементом. При построении исходной последовательности элементов требуется, чтобы некоторые из них имели потомков, поэтому она строится из элементов Employee, т.к. у них есть некоторые потомки:

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"))));

            // Получаем все элементы Employee
            IEnumerable<XElement> elements = xDoc.Element("Employees").Elements("Employee");

            foreach (XElement e in elements)
            {
                Console.WriteLine("Исходный элемент: {0} значение = {1}", e.Name, e.Value);
            }

            Console.WriteLine();

            foreach (XNode node in elements.DescendantNodes())
            {
                Console.WriteLine("Узел-потомок: " + node);
            }

Сначала строится дерево XML и исходная последовательность элементов. В данном случае исходная последовательность содержит элементы Employee. Затем на исходной последовательности вызывается операция DescendantNodes и отображаются результаты:

Вызов единственного прототипа DescendantNodes

Обратите внимание, что в результате получаются не только элементы-потомки, но также и комментарий. Также обратите внимание, что для каждого элемента в документе XML получаются по два узла. Например, есть узел, значение которого выглядит как "<FirstName>Alex</FirstName>", а также узел со значением "Alex". Первый узел в паре — элемент FirstName. Второй узел — XText для этого элемента. Не забывайте об этих автоматически создаваемых объектах XText.

DescendantNodesAndSelf

Операция DescendantNodesAndSelf может быть вызвана на последовательности элементов и возвращает последовательность, содержащую собственно каждый исходный элемент и его узлы-потомки.

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

public static IEnumerable<XNode> DescendantNodesAndSelf ( 
      this IEnumerable<XElement> source
      )

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

Для демонстрации работы этой операции применяется тот же пример, что использовался для демонстрации DescendantNodes, просто с заменой ее на DescendantNodesAndSelf, как показано ниже:

...
foreach (XNode node in elements.DescendantNodesAndSelf())
{
     Console.WriteLine("Узел-потомок: " + node);
}

Вопрос в том, будет ли вывод таким же, как и у примера DescendantNodes, только с включением исходных элементов? Можете убедиться в этом:

Вызов единственного прототипа DescendantNodesAndSelf

В выводе присутствуют не только сами элементы Employee и их потомки, но также один узел, не являющийся элементом — комментарий. В этом состоит отличие между операциями DescendantNodesAndSelf и описанной в следующей статье Descendants, которая пропускает узлы, не являющиеся элементами.

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