В чём отличие между методом Nodes и Descendants?

В чём разница между методом Nodes и Descendants?

В этой статье хочу рассказать про метод Descendants и показать его отличие от метода Nodes при работе с xml узлами типа XElement.

Метод Nodes

И так предположим, что у нас есть xml файл, который например, содержит следующую структуру:

<friends>
<friend id="1">
<name>Иван</name>
<lastname>Иванов</lastname>
<age>22</age>
</friend>
<!--комментарий-->
<friend id="2">
<name>Петр</name>
<lastname>Петров</lastname>
<age>23</age>
</friend>
</friends>

И нам нужно получить значение элемента name содержащегося в каждом узле friend. Для решения данной задачи воспользуемся методом Nodes.

foreach (XElement elm in xDoc.Root.Nodes())
{
Console.WriteLine(elm.Element("name").Value);
}

В результате выполнения данного цикла происходит выброс исключения:

Unable to cast object of type System.Xml.Linq.XComment
to type System.Xml.Linq.XElement.

Это происходит, потому что в приведенном примере мы не учли, что тип xml узла может быть не только XElement, но и XComment, как например в данном случаи.

Чтобы это исправить мы можем поступить, например следующим образом:

XDocument xDoc = XDocument.Load(@"../../имя_файла.xml");
foreach (XNode node in xDoc.Root.Nodes())
{
//получаем значение элемента
}

XNode &#8212; это всего лишь абстрактная концепция представление узла, которым может являться: комментарий (XComment), элемент (XElement), тип документа или текстовый узел (XText) в xml дереве.

Так как тип xml узла каждый раз может быть разным, то для того чтобы получить все узлы только типа XElement необходимо в теле цикла добавить проверку:

foreach (XNode node in xDoc.Root.Nodes())
{
if (node.NodeType == System.Xml.XmlNodeType.Element)
{
//получаем значение элемента
}
}

После того как мы произвели отбор по типу, необходимо выполнить операцию явного приведения, чтобы получить доступ к членам класса XElement.

foreach (XNode node in xDoc.Root.Nodes())
{
if (node.NodeType == System.Xml.XmlNodeType.Element)
{
string name = ((XElement)node).Element("name").Value;
}
}

Либо для решения обоих задач можно воспользоваться операторами: is или as.

foreach (XNode node in xDoc.Root.Nodes())
{
XElement elm = node as XElement;
if (elm != null)
{
string name = elm.Element("name").Value;
}
}

Метод Descendants

Кроме метода Nodes в сборке System.Xml.Linq так же содержится метод Descendants, который позволяет нам избавиться от всех выше описанных возникающих &#171;проблем&#187; одним разом. Так как в результате выполнения данного метода мы всегда получаем коллекцию элементов типа XElement, например:

foreach (XElement elm in xDoc.Descendants("friend"))
{
//действия
}

На этом всё если есть какие-то вопросы, то оставляйте их в комментариях.

Читайте также:

Leave a Reply

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*