Теперь, когда ваше приложение может подключаться к сети и управлять использованием сети, пришло время начать работу с данными. На сегодняшний день в Интернете используются два наиболее распространенных формата данных: расширяемый язык разметки (XML) и объектная нотация JavaScript (JSON). Веб-сайты, которые часто обновляют свое содержимое, например блоги, часто предоставляют XML-канал, чтобы приложения могли следить за изменениями содержимого. Этот раздел покажет вам, как анализировать XML-документ и использовать его данные в ваших приложениях.
Первое, что вам нужно сделать, это выбрать XML-фид, который вы хотите использовать в своем приложении. Для этого раздела будет использоваться лента из StackOverflow.com , ориентированная на Windows 8. Канал доступен по адресу http://stackoverflow.com/feeds/tag/windows-phone-8 .
После того, как вы определили канал, вы захотите проанализировать его, чтобы определить, какие поля представляют интерес для вашего приложения. Ниже приведен пример абстрактной формы фида StackOverflow.com, который мы будем использовать:
<?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:re="http://purl.org/atompub/rank/1.0"> <title type="text">active questions tagged windows-phone-8 - Stack Overflow</title> ... <entry> ... </entry> <entry> <id>http://stackoverflow.com/q/00000000</id> <re:rank scheme="http://stackoverflow.com">0</re:rank> <title type="text">Windows Phone XML Data</title> <category scheme="http://stackoverflow.com/feeds/tag/windows-phone-8/tags" term="c#"/> <category scheme="http://stackoverflow.com/feeds/tag/windows-phone-8/tags" term="xml"/> <category scheme="http://stackoverflow.com/feeds/tag/windows-phone-8/tags" term="windows-8"/> <category scheme="http://stackoverflow.com/feeds/tag/windows-phone-8/tags" term="windows-runtime"/> <author> <name>anonymous</name> <uri>http://stackoverflow.com/users/000000</uri> </author> <link rel="alternate" href="http://stackoverflow.com/questions/00000000/windows-store-xml-data" /> <published>1900-01-01T00:00:00Z</published> <updated>1900-01-01T00:00:00Z</updated> <summary type="html"> <p>How do I use XML in Windows Phone apps?</p> </summary> </entry> <entry> ... </entry> ... </feed>
Для примера мы сосредоточимся на элементах title , link и summary . Первым шагом является создание класса, который представляет данные, с которыми вы хотите работать в вашем приложении. Поскольку мы фокусируемся на элементах заголовка, ссылки и сводки, класс будет выглядеть следующим образом:
public class FeedEntry { public string Title { get; set; } public string Link { get; set; } public string Summary { get; set; } }
Следующим шагом является создание класса и метода, который будет отвечать за анализ:
public class StackOverflowXmlParser { ... }
Поскольку мы будем подключаться к интернет-ресурсу для получения данных XML, мы хотим сделать это асинхронно, чтобы избежать блокировки других операций. Как только мы получим данные и разберем их в списке объектов FeedEntry, мы вызовем событие, чтобы сообщить вызывающей стороне, что операция завершена. Это можно сделать с помощью следующего:
... public event EventHandler<List<FeedEntry>> ParseCompleted; ...
Далее нам понадобится метод, который запускает асинхронную процедуру для получения данных и их анализа:
... public void ParseAsync() { var connectionState = GetConnectionState(); if (connectionState == ConnectionState.WiFi || connectionState == ConnectionState.Ethernet) { var request = WebRequest.CreateHttp("http://stackoverflow.com/feeds/tag/windows-8"); request.BeginGetResponse(BeginGetResponseCallback, request); } } ...
Этот код делает пару вещей. Сначала он получает текущий тип интернет-соединения, которое имеет устройство. Если устройство подключено к соединению WiFi или Ethernet, оно приступает к созданию объекта HttpWebRequest и вызывает его метод BeginGetResponse . Это начинает асинхронный запрос к StackOverflow для конкретного интересующего нас фида. Первым параметром этого метода является обратный вызов, который будет вызван при получении ответа. Второй параметр вызова — это любое состояние, которое мы хотим использовать в обратном вызове. В этом случае мы хотим убедиться, что мы получаем доступ к исходному HttpWebRequest, поэтому мы просто пропускаем его.
Мы будем использовать обратный вызов для анализа данных. Первое, что мы хотим сделать в этом методе, — это создать список объектов FeedEntry для сохранения результатов.
... private void BeginGetResponseCallback(IAsyncResult asyncResult) { List<FeedEntry> results = new List<FeedEntry>(); ... } ...
Далее нам нужно получить поток ответов, содержащий данные, которые мы хотим проанализировать:
... var request = (HttpWebRequest)asyncResult.AsyncState; var response = request.EndGetResponse(asyncResult); var responseStream = response.GetResponseStream(); ...
Следующее, что нужно сделать, это определить метод, с помощью которого будет обрабатываться канал. Поскольку мы имеем дело с фидом XML, у нас есть три варианта в .NET:
- Пространство имен System.Xml
- Пространство имен System.Xml.Linq
- System.ServiceModel.Syndication имен
Пространство имен System.Xml обеспечивает основанную на стандартах поддержку для обработки XML. Он дает вам немного контроля над тем, как вы обрабатываете XML, и позволяет вам использовать такие вещи, как схемы XSD, выражения XPath и преобразования XSLT. Это немного больше энергии, чем нам нужно для этой конкретной задачи. Класс SyndicationFeed в пространстве имен System.ServiceModel.Syndication фактически сделает нашу работу невероятно простой, если мы хотим работать со всеми полями в ленте. Однако, поскольку нас интересуют только три поля, мы будем использовать пространство имен System.Xml.Linq. Это пространство имен содержит классы для LINQ (Language INtegrated Query) to XML, который служит интерфейсом программирования XML в памяти, который обеспечивает простую и эффективную обработку документов XML.
Прежде всего, при работе с LINQ to XML необходимо создать несколько объектов XName, которые представляют имена элементов, с которыми мы хотим работать. Эти имена должны включать локальные имена и имена пространств имен.
//Atom namespace var atomNamespace = "http://www.w3.org/2005/Atom"; //Create the names of the XML elements including the Atom namespace var entryXName = XName.Get("entry", atomNamespace); var titleXName = XName.Get("title", atomNamespace); var linkXName = XName.Get("link", atomNamespace); var summaryXName = XName.Get("summary", atomNamespace);
Следующим шагом является загрузка данных XML в потоке ответов в новый экземпляр класса XElement .
... XElement root = XElement.Load(responseStream); ...
Android-совет |
Это похоже на использование Android HttpURLConnection для получения и InputStream |
private InputStream downloadXml() throws IOException { URL url = new URL('http://stackoverflow.com/feeds/tag/windows-8'); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setDoInput(true); conn.connect(); return conn.getInputStream(); }
Затем вы должны использовать вывод InputStream в качестве входного параметра в методе setInput класса XmlPullParser .
Как только объект XElement загружен, мы можем использовать LINQ для запроса только элементов ввода и в XElement и сохранить их в списке:
//Load all "entry" elements from the XML into a list var entries = (from e in root.Elements(entryXName) select e).ToList();
Далее мы начнем перебирать список записей. Первым шагом в итерации является создание нового объекта FeedEntry:
//Iterate all "entry" elements foreach (var entry in entries) { //Create a new FeedEntry var feedEntry = new FeedEntry(); ... }
Затем мы присвоим значение свойства Title FeedEntry значению элемента title:
//Get the title var titleElement = (from e in entry.Elements(titleXName) select e).FirstOrDefault(); if (titleElement != null) feedEntry.Title = titleElement.Value;
Android-совет |
Эквивалент Android будет вызывать метод getText () класса XmlPullParser, чтобы получить значение текущего элемента. |
Аналогичным образом мы присвоим значение свойства Link значению атрибута href элемента link:
//Get the link var linkElement = (from e in entry.Elements(linkXName) select e).FirstOrDefault(); if (linkElement != null) { var hrefAttribute = linkElement.Attributes("href").FirstOrDefault(); if (hrefAttribute != null) feedEntry.Link = hrefAttribute.Value; }
Android-совет |
Чтобы получить значение атрибута в Android, вы должны использовать метод getAttribueValue () класса XmlPullParser. |
Далее мы присвоим значение свойства Summary значению элемента summary и добавим объект в набор результатов, который будет возвращен вызывающему методу:
//Get the summary if (summaryElement != null) feedEntry.Summary = WebUtility.HtmlDecode(summaryElement.Value); //Add to the entry to the result set results.Add(feedEntry);
Затем нам нужно вызвать событие, чтобы сообщить исходному вызывающему методу, что анализ завершен:
if (this.ParseCompleted != null) this.ParseCompleted(this, results);
Последний шаг — вызов метода ParseAsync и ответ на событие ParseCompleted .
public void GetXmlData() { var parser = new StackOverlfowParser(); parser.ParseCompleted += parser_ParseCompleted; parser.ParseAsync(); } private void parser_ParseCompleted(object sender, List<FeedEntry> e) { //do something with the results }
Это оно! Ваше приложение Windows Phone теперь может работать с данными из Интернета.