Операция InDocumentOrder
53LINQ --- LINQ to XML --- Операция InDocumentOrder
Операция InDocumentOrder может быть вызвана на последовательности узлов и возвращает последовательность, содержащую дочерние узлы каждого исходного узла в порядке их следования в документе. Эта операция имеет один прототип, который описан ниже:
public static IErmmerable<T> InDocumentOrder<T> (
this IEnumerable<T> source
) where T : XNode
Эта версия вызывается на последовательности указанного типа, элементы которой должны быть узлами или типами-наследниками узлов, и возвращает последовательность того же типа, содержащую дочерние узлы исходных узлов в порядке их следования в документе.
Эта довольно странная операция. В данном примере понадобится последовательность узлов. Поскольку в дополнение к элементам нужно видеть некоторые узлы, которые не являются элементами, будет построена последовательность узлов, дочерних по отношению к элементам Employee. Это необходимо потому, что один из них имеет комментарий, который является узлом, но не элементом. Исходный код представлен ниже:
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<XNode> nodes =
xDoc.Element("Employees").Elements("Employee").Nodes().Reverse();
// Сначала отобразим все исходные узлы
foreach (XNode node in nodes)
{
Console.WriteLine("Исходные узлы: {0}", node);
}
Console.WriteLine();
// Теперь отобразим дочерние узлы каждого исходного узла
foreach (XNode node in nodes.InDocumentOrder())
{
Console.WriteLine("Упорядоченный узел: {0}", node);
}
В коде строится дерево XML. Для построения исходной последовательности с помощью операции Nodes извлекаются дочерние узлы элемента Employee, а затем вызывается стандартная операция запроса Reverse.
Операция Reverse возвращает последовательность входных элементов, выстроенную в обратном порядке. Теперь имеется последовательность узлов, расположенных не в исходном порядке. Этот дополнительный шаг по изменению порядка предпринимается для того, чтобы при вызове операции InDocumentOrder было обнаружено отличие. Затем отображаются исходные узлы в неупорядоченном виде, вызывается операция InDocumentOrder и получается следующий результат:
Как видите, исходные узлы расположены в порядке, противоположном тому, в котором они были построены в коде, а упорядоченные узлы оказываются опять в своем исходном порядке. Отлично, хотя и странно.