7 марта 2011 в 11:39

Простой пример выполнения HTTP-запроса к web-сервису и разбор XML-ответа

Привет всем хабровчанам!

Сразу хочу сказать, что, хотя тема не «Hello world», но рассматриваемая задача довольно проста и приведена здесь на Хабре скорее в качестве средства экономии времени для разработчиков, которым, возможно, надо будет поработать с XML-ответами от web-сервисов. Для XML-разбора я использовал DOMparser (я знаю и про SAXParser, конечно) как это привычно для меня в PHP.

У Приватбанка (Украина) имеется API, с которым можно ознакомиться здесь. После изучения его становится ясно, что сервис достаточно информативный и было бы удобно иметь на мобильном устройстве средство общения с ним. Посмотрим как можно опросить этот сервис и получить такую избитую, но иногда полезную информацию как актуальный курс валют. После прочтения топика, в принципе, не составит труда написать и другие полезные функции.



Сервис работает предсказуемым образом. Вы формируете запрос:

privat24.privatbank.ua/p24/accountorder?oper=prp&PUREXML&apicour&country=ru

и в ответ получаете XML-ответ вида:

<account_order>
     <support/>
     <version buildNum="2042" buildDate="Thu Nov 29 10:40:45 EET 2007"/>
     <logged sessioncount="1073" visitscount="298"/> 
     <locale language="ru"> 
           <date id="20090807T17:21:59" traditional="07.08.2009">07 авг 2009,Пт 17:21:59</date>
     </locale>
     <request url_base="https://privat24.privatbank.ua/p24/" url="/accountorder" os="Win" win="Y" ie="N"/>
     <info> 
           <role id="2"/> 
           <dump exchange="" oper="prp" PUREXML="" apicour="" country="ru" /> 
     </info>

     <exchangerate>
           <exchangerate ccy="EUR" ccy_name_ru="Евро" ccy_name_ua="Євро " ccy_name_en="Euro" base_ccy="RU" buy="450476"
                  unit="1" date="2009-08-26 00:00:00.0"/>
           <exchangerate ccy="USD" ccy_name_ru="Доллар США" ccy_name_ua="Долар США" ccy_name_en="US Dollar"
                  base_ccy="RU" buy="315437" unit="1" date="2009-08-26 00:00:00.0"/>

      <exchangerate>
</account_order>


Здесь нас интересуют узлы exchangerate с атрибутом buy (сервис отдает значения курса покупки в копейках).

Для работы я сделал интерфейс проще не придумаешь (TextView+кнопка):



И для кнопки написал следующий код:

   public void getCurrencyClick(View v){
    	TextView tv = (TextView) findViewById(R.id.CurrencyTextView);
  
    	try{
 /*
  определяем URL сервиса
  готовим API, позволяющий выполнять разбор документа
  загружаем в парсер полученный ответ и вызываем метод parse   		
  */
    	URL url = new URL("https://privat24.privatbank.ua/p24/accountorder?oper=prp&PUREXML&apicour&country=ua");
    	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    	DocumentBuilder db = dbf.newDocumentBuilder();
    	Document doc = db.parse(new InputSource(url.openStream()));
    	doc.getDocumentElement().normalize();
 /*получаем агрегатный узел с дочерними узлами с атрибутами, хранящими значения валют;   
 в ответе всего два узла, мы возьмем первый, а при необходимости тут вполне можно запустить цикл с nodeList.getLength 
*/
 	
    	NodeList nodeList = doc.getElementsByTagName("exchangerate");
    	Node node = nodeList.item(0);
 // опускаемся на узел ниже и получаем список его атрибутов
    	NamedNodeMap attributes = node.getFirstChild().getAttributes();
 //получаем значение атрибут buy      	
    	Node currencyAttribEUR  = attributes.getNamedItem("buy");
 // ... и его значение   	
    	String currencyValueEUR = currencyAttribEUR.getNodeValue();  	
    
 // аналогично поступаем с датой, чтобы иметь представление о актуальности   	
    	Node dateCurrency       = attributes.getNamedItem("date");
    	String dateCurrencyStr  = dateCurrency.getNodeValue();
 // и выводим информацию   	
    	tv.setText("Курс евро на "+dateCurrencyStr+":"+currencyValueEUR+ "коп");
    	   	
    	}
    	catch (Exception e) {
    		tv.setText("Не удалось выполнить операцию");
    	};
    	
 
    	}


На мой взгляд — довольно просто. Еще раз напоминаю, что это тестовое приложение, которое, искренне надеюсь, окажется полезным для кого-нибудь.

Спасибо за внимание;)
Евгений @jeston
карма
81,2
рейтинг 0,0
Пользователь
Самое читаемое Разработка

Комментарии (16)

  • 0
    А если использовать XPath? ДУмаю, будет проще, и короче.
    • +1
      XPath xpath = XPathFactory.newInstance().newXPath();
      String expression = "/account_order/exchangerate";
      InputSource inputSource = new InputSource(url.openStream());
      NodeSet nodes = (NodeSet) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);
      


      Едва ли короче, но это дело вкуса, наверно.
  • +4
    В чем ценность примера-то, если уж быть честным?

    try {
    }
    catch (Exception e) {
    tv.setText("Не удалось выполнить операцию");
    };

    А вот за это…
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Ну что же, искренне спасибо вам за замечание, я не знал об Jaxb. Теперь восполню этот пробел.
      • НЛО прилетело и опубликовало эту надпись здесь
        • +1
          вместо использования таких маппингов надо оторвать руки за то что нету указаной схемы в xml
  • 0
    Эх, когда же новички, наконец, научатся использовать AsyncTask…
    • 0
      Спасибо за замечание, я в курсе дела, просто я не стал повторяться — статья об этом уже есть.
    • +1
      с обычным потоком тоже весело и вкусно!
  • НЛО прилетело и опубликовало эту надпись здесь
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Спасибо))
        Да, есть, конечно, сокеты.
        Мой следующий топик их несколько касается.
        • НЛО прилетело и опубликовало эту надпись здесь

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.