Простой пример выполнения 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("Не удалось выполнить операцию");
        	};
        	
     
        	}
    


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

    Спасибо за внимание;)
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 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
                Спасибо))
                Да, есть, конечно, сокеты.
                Мой следующий топик их несколько касается.
                • НЛО прилетело и опубликовало эту надпись здесь

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