This article has been localized into Russian by the community.
Использование XPath с классом XmlDocument
В предыдущей главе мы читали XML-файл с помощью класса XmlDocument. Мы сделали это через доступ к свойству ChildNodes, что было легко, потому что пример был очень простым. Это не делало наш код особенно читабельным, поэтому в этой главе мы рассмотрим другой подход, более мощный и более простой для понимания и поддержки. Технология, которую мы будем использовать называется XPath и поддерживается той же организацией, которая разработала стандарт XML. XPath - это фактически целый язык запросов с множеством возможностей, но поскольку это не учебник по XPath, мы рассмотрим только базовые запросы. Тем не менее даже в этих простейших формах XPath достаточно мощный, как вы сможете увидеть в следующих примерах.
В классе XmlDocument есть несколько методов, принимающих запрос XPath в качестве параметра и затем возвращающих результирующий узел или узлы XmlNode. В этой главе мы рассмотрим два метода. Метод SelectSingleNode(), который возвращает один XmlNode, на основе переданного запроса XPath, и метод SelectNodes(), который возвращает коллекцию объектов XmlNode (XmlNodeList), на основе переданного запроса XPath.
Мы попробуем оба эти метода, но вместо XML-данных о валюте, которые мы обрабатывали в предыдущих главах, мы попробуем новые данные XML. RSS-каналы - это в сущности XML-документы, собранные особым образом, чтобы позволить разным читателям новостей загружать, обрабатывать и отображать одну и ту же информацию по-своему.
Мы будем использовать RSS-каналы из CNN, которые можно найти по ссылке http://rss.cnn.com/rss/edition_world.rss, с новостями со всего мира. Если вы откроете ссылку в своем браузере, ваш браузер сможет представить все это в удобном виде, позволяя вам увидеть обзор канала и подписаться на него, однако внутри это просто XML, который можно увидеть, если выбрать "Просмотреть код" в вашем браузере. Вы увидите, что корневой элемент называется "rss". Элемент rss обычно содержит один или несколько элементов "channel", и внутри этого элемента мы можем найти информацию о ленте новостей, а также узлы "item", являющиеся как раз теми новостями, которые мы хотим получить.
В следующем примере мы будем использовать метод SelectSingleNode(), чтобы получить заголовок новостей. Если вы посмотрите XML, вы увидите элемент <title> в качестве дочернего для элемента <channel>, который в свою очередь является дочерним для элемента <rss>, корневого. Этот запрос можно описать в XPath следующим образом:
//rss/channel/title
Мы просто записали имена искомых элементов, разделенные прямым слэшем (/), который показывает, что элемент должен быть дочерним для элемента, расположенного до прямого слэша. Использование такого XPath просто, как показано ниже:
using System;
using System.Text;
using System.Xml;
namespace ParsingXml
{
class Program
{
static void Main(string[] args)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("http://rss.cnn.com/rss/edition_world.rss");
XmlNode titleNode = xmlDoc.SelectSingleNode("//rss/channel/title");
if(titleNode != null)
Console.WriteLine(titleNode.InnerText);
Console.ReadKey();
}
}
}
Мы используем метод SelectSingleNode(), чтобы получить элемент <title>, который принимает наш XPath как параметр. Затем мы проверяем, что был возвращен результат и если был, выводим на экран InnerText этого узла, который и должен оказаться заголовком новости.
В следующем примере мы будем использовать метод SelectNodes(), чтобы найти все узлы элементов в новостях и вывести на экран информацию о них:
using System;
using System.Text;
using System.Xml;
namespace ParsingXml
{
class Program
{
static void Main(string[] args)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("http://rss.cnn.com/rss/edition_world.rss");
XmlNodeList itemNodes = xmlDoc.SelectNodes("//rss/channel/item");
foreach(XmlNode itemNode in itemNodes)
{
XmlNode titleNode = itemNode.SelectSingleNode("title");
XmlNode dateNode = itemNode.SelectSingleNode("pubDate");
if((titleNode != null) && (dateNode != null))
Console.WriteLine(dateNode.InnerText + ": " + titleNode.InnerText);
}
Console.ReadKey();
}
}
}
Метод SelectNodes() принимает запрос XPath как строку, как мы видели в предыдущем примере, и затем возвращает список объектов XmlNode в коллекцию XmlNodeList . Мы проходимся в цикле по каждому из них и по каждому элементу узла, запрашивая дочерний узел с именем title (заголовок) и pubDate (published date - дата публикации), используя SelectSingleNode() элемента узла. Если мы получили и то и другое, выводим на экран дату и заголовок в одну строку и движемся дальше.
В нашем примере мы хотели получить два разных значения из каждого элемента узла, вот почему мы запрашивали элементы узлов и затем рассматривали каждый из них. Однако если нам нужны только заголовки, мы должны изменить запрос XPath, как показано ниже:
//rss/channel/item/title
Он будет соответствовать каждому узлу title в каждом из элементов узлов. Ниже приводится запрос с кодом С#, чтобы все это выполнить:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("http://rss.cnn.com/rss/edition_world.rss");
XmlNodeList titleNodes = xmlDoc.SelectNodes("//rss/channel/item/title");
foreach(XmlNode titleNode in titleNodes)
Console.WriteLine(titleNode.InnerText);
Console.ReadKey();