В чём разница между методом 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 — это всего лишь абстрактная концепция представление узла, которым может являться: комментарий (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, который позволяет нам избавиться от всех выше описанных возникающих «проблем» одним разом. Так как в результате выполнения данного метода мы всегда получаем коллекцию элементов типа XElement, например:
foreach (XElement elm in xDoc.Descendants("friend")) { //действия }
На этом всё если есть какие-то вопросы, то оставляйте их в комментариях.
Читайте также: