Персональный блог Игоря Антонова aka "spider_net"

Как получить курс валюты средствами C#


Рубрика: c# -> Программирование
Метки: |
Просмотров: 19138
Как получить курс валюты средствами C#

Одному из наших новых корпоративных сервисов требуется регулярно получать актуальный курс валюты. Нас интересуют евро и доллары, особенно сейчас, когда курс стал резко скакать. Чтобы успевать за обновлениями и освободить вечно занятых сотрудников от этой рутиной операции, было решено автоматизировать этот процесс. К счастью, исходный код проекта у нас имеется.

Особого времени на решения этой задачи не было, и я надеялся, что в сети найдется готовый снипет, способный решить проблему за пару минут. Увы, ни к чему хорошему мои поиски не привели. Варианты, попавшие под зоркий глаз Google, демонстрировали банальный анализ страницы центрального банка с перечнем всех доступных курсов валют при помощи регулярного выражения. Не знаю, зачем авторы этих решений мучились с регулярными выражениями, если сайт центрального банка всегда рад отдать интересующую информацию в виде XML/SOAP.

Вариант с SOAP мне показался более затратным (по времени), поэтому было решено получать все необходимые данные в XML. Для этого требуется сделать GET запрос по адресу http://www.cbr.ru/scripts/XML_daily.asp. Ответом будет готовый для анализа XML, содержащий информацию о курсах различных валют (на текущую дату). Кусок такого XML привожу ниже:

<ValCurs Date="18.03.2014" name="Foreign Currency Market">
 <Valute ID="R01010">
 <NumCode>036</NumCode>
 <CharCode>AUD</CharCode>
 <Nominal>1</Nominal>
 <Name>Австралийский доллар</Name>
 <Value>33,2054</Value>
</Valute>
<Valute ID="R01020A">
 <NumCode>944</NumCode>
 <CharCode>AZN</CharCode>
 <Nominal>1</Nominal>
 <Name>Азербайджанский манат</Name>
< Value>46,7958</Value>
</Valute>
<Valute ID="R01035">
 <NumCode>826</NumCode>
 <CharCode>GBP</CharCode>
 <Nominal>1</Nominal>
 <Name>Фунт стерлингов Соединенного королевства</Name>
 <Value>60,9791</Value>
</Valute>
<Valute ID="R01060">
 <NumCode>051</NumCode>
 <CharCode>AMD</CharCode>
 <Nominal>1000</Nominal>
 <Name>Армянских драмов</Name>
 <Value>88,2613</Value>
</Valute>
<Valute ID="R01090">
 <NumCode>974</NumCode>
 <CharCode>BYR</CharCode>
 <Nominal>10000</Nominal>
 <Name>Белорусских рублей</Name>
 <Value>37,2654</Value>
</Valute>

Получение курсов валют средствами C#

Решить задачу получения курса средствами C# достаточно просто. Возможно, это не совсем оптимальное решение (я пока не считаю себя экспертом в .NET), но оно работает шустро и прекрасно выполняет поставленную задачу. Разбирать XML я решил при помощи класса XmlTextReader. Вот что у меня получилось:

using System.Xml;
//Инициализируем объекта типа XmlTextReader и
//загружаем XML документ с сайта центрального банка
XmlTextReader reader = new XmlTextReader ("http://www.cbr.ru/scripts/XML_daily.asp" );
//В эти переменные будем сохранять куски XML
//с определенными валютами (Euro, USD)
string USDXml = "" ;
string EuroXML = "" ;
//Перебираем все узлы в загруженном документе
while (reader.Read())
{
   //Проверяем тип текущего узла
   switch (reader.NodeType)
   {
    //Если этого элемент Valute, то начинаем анализировать атрибуты
    case XmlNodeType.Element:
      
      if (reader.Name == "Valute")
      {
        if (reader.HasAttributes)
        {
         //Метод передвигает указатель к следующему атрибуту
          while (reader.MoveToNextAttribute())
          {
           if (reader.Name == "ID")
           {
            //Если значение атрибута равно R01235, то перед нами информация о курсе доллара
             if (reader.Value == "R01235")
             {
             //Возвращаемся к элементу, содержащий текущий узел атрибута
               reader.MoveToElement();
               //Считываем содержимое дочерних узлом
                USDXml = reader.ReadOuterXml();
              }
            }
            
            //Аналогичную процедуру делаем для ЕВРО
            if (reader.Name == "ID")
            {
              if (reader.Value == "R01239")
              {
                reader.MoveToElement();
                EuroXML = reader.ReadOuterXml();
              }
            }
         }
       }
     }
     
     break;
    }
  }
  
  //Из выдернутых кусков XML кода создаем новые XML документы
  XmlDocument usdXmlDocument = new XmlDocument ();
  usdXmlDocument.LoadXml(USDXml);
  XmlDocument euroXmlDocument = new XmlDocument ();
  euroXmlDocument.LoadXml(EuroXML);
  //Метод возвращает узел, соответствующий выражению XPath
  XmlNode xmlNode = usdXmlDocument.SelectSingleNode( "Valute/Value");
       
  //Считываем значение и конвертируем в decimal. Курс валют получен
  decimal usdValue = Convert.ToDecimal(xmlNode.InnerText);
  xmlNode = euroXmlDocument.SelectSingleNode( "Valute/Value");
  decimal euroValue = Convert.ToDecimal(xmlNode.InnerText);

В принципе, можно было обойтись средствами одного XmlTextReader, но тогда код получился бы более сложным для восприятия. Пришлось бы работать с элементами последовательно и сохранять промежуточные значения для дальнейшего анализа. Смешанный подход позволил избавиться от излишеств.

Кстати, эту же задачу реально решить при помощи одного класса XmlDocument. XML файл с информацией о курсах валют небольшого размера, поэтому использование XmlDocument вполне оправданно. Для больших файлов XmlDocument не подходит, т.к. все данные из файла сразу же загружаются в память и ее элементарно может не хватить.

Комментариев: 2 RSS

Интересно!

У меня по работе тоже часто стоит задача в анализе xml. Нам в этом очень помогает механизм JAXB ru.m.wikipedia.org/wiki/Java_Architecture_for_XML_Binding

То есть мы можем определенным xml ставить в соответствии свои java классы и после демаршалинга работать с объектом, который хранит в своих свойствах данные из xml. Нам приходт строка xml. Мы ее демаршалим и получаем наш объект. Очень удобно и не нужно писать свой парсер. Не знаю есть ли подобный механизм под .NET

2Kastor,

Да, в .NET тоже так можно. Насколько мне известно есть несколько способов решения подобной задачи, но самый простой способ - воспользоваться ExpandoObject. Возможность появилась в четвертой версии .NET Framework. С их помощью можно собрать произвольный объект из XML.

Оставьте комментарий!
comments powered by HyperComments