В этом уроке:

- парсим XML с помощью XmlPullParser

 

XmlPullParser – XML-парсер, который можно использовать для разбора XML документа. Принцип его работы заключается в том, что он пробегает весь документ, останавливаясь на его элементах. Но пробегает он не сам, а с помощью метода next. Мы постоянно вызываем метод next и с помощью метода getEventType проверяем, на каком элементе парсер остановился.

Основные элементы документа, которые ловит парсер:

START_DOCUMENT – начало документа

START_TAG – начало тэга

TEXT – содержимое элемента

END_TAG – конец тэга

END_DOCUMENT – конец документа

 

Напишем приложение, которое возьмет xml-файл и разберет его на тэги и аттрибуты.

 

Создадим проект:

Project name: P0791_ XmlPullParser
Build Target: Android 2.3.3
Application name: XmlPullParser
Package name: ru.startandroid.develop.p0791xmlpullparser
Create Activity: MainActivity

 

В папке res создайте папку xml, и в ней создайте файл data.xml:

<?xml version="1.0" encoding="utf-8"?>
<data>
	<phone>
		<company>Samsung</company>
		<model>Galaxy</model>
		<price>18000</price>
		<screen multitouch="yes" resolution="320x480">3</screen>
		<colors>
			<color>black</color>
			<color>white</color>
		</colors>
	</phone>
</data>

Это файл с описанием телефона Samsung Galaxy. Указаны его цена, характеристики экрана и возможные цвета корпуса. Данные выдуманы и могут не совпадать с реальностью :)

 

MainActivity.java:

package ru.startandroid.develop.p0791xmlpullparser;

import java.io.IOException;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

public class MainActivity extends Activity {

  final String LOG_TAG = "myLogs";

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    String tmp = "";

    try {
      XmlPullParser xpp = prepareXpp();

      while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
        switch (xpp.getEventType()) {
        // начало документа
        case XmlPullParser.START_DOCUMENT:
          Log.d(LOG_TAG, "START_DOCUMENT");
          break;
        // начало тэга
        case XmlPullParser.START_TAG:
          Log.d(LOG_TAG, "START_TAG: name = " + xpp.getName()
              + ", depth = " + xpp.getDepth() + ", attrCount = "
              + xpp.getAttributeCount());
          tmp = "";
          for (int i = 0; i < xpp.getAttributeCount(); i++) {
            tmp = tmp + xpp.getAttributeName(i) + " = "
                + xpp.getAttributeValue(i) + ", ";
          }
          if (!TextUtils.isEmpty(tmp))
            Log.d(LOG_TAG, "Attributes: " + tmp);
          break;
        // конец тэга
        case XmlPullParser.END_TAG:
          Log.d(LOG_TAG, "END_TAG: name = " + xpp.getName());
          break;
        // содержимое тэга
        case XmlPullParser.TEXT:
          Log.d(LOG_TAG, "text = " + xpp.getText());
          break;

        default:
          break;
        }
        // следующий элемент
        xpp.next();
      }
      Log.d(LOG_TAG, "END_DOCUMENT");

    } catch (XmlPullParserException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  XmlPullParser prepareXpp() {
    return getResources().getXml(R.xml.data);
  }
} 

В onCreate мы получаем XmlPullParser с помощью метода prepareXpp и начинаем его разбирать. Затем в цикле while мы запускаем прогон документа, пока не достигнем конца - END_DOCUMENT. Прогон обеспечивается методом next в конце цикла while. В switch мы проверяем на каком элементе остановился парсер.

START_DOCUMENT – начало документа

START_TAG – начало тега. Выводим в лог имя тэга, его уровень в дереве тэгов (глубину) и количество атрибутов. Следующей строкой выводим имена и значения атрибутов, если они есть.

END_TAG – конец тэга. Выводим только имя.

TEXT – содержимое тэга

 

В методе prepareXpp мы подготавливаем XmlPullParser. Для этого вытаскиваем данные из папки res/xml. Это аналогично вытаскиванию строк или картинок – сначала получаем доступ к ресурсам (getResources), затем вызываем метод, соответствующий ресурсу. В нашем случае это - метод getXml. Но возвращает он не xml-строку , а готовый XmlPullParser.

Все сохраним и запустим приложение.

 

Смотрим лог:

START_DOCUMENT
START_DOCUMENT
START_TAG: name = data, depth = 1, attrCount = 0
START_TAG: name = phone, depth = 2, attrCount = 0
START_TAG: name = company, depth = 3, attrCount = 0
text = Samsung
END_TAG: name = company
START_TAG: name = model, depth = 3, attrCount = 0
text = Galaxy
END_TAG: name = model
START_TAG: name = price, depth = 3, attrCount = 0
text = 18000
END_TAG: name = price
START_TAG: name = screen, depth = 3, attrCount = 2
Attributes: multitouch = yes, resolution = 320x480,
text = 3
END_TAG: name = screen
START_TAG: name = colors, depth = 3, attrCount = 0
START_TAG: name = color, depth = 4, attrCount = 0
text = black
END_TAG: name = color
START_TAG: name = color, depth = 4, attrCount = 0
text = white
END_TAG: name = color
END_TAG: name = colors
END_TAG: name = phone
END_TAG: name = data
END_DOCUMENT
START_DOCUMENT
START_DOCUMENT
START_TAG: name = data, depth = 1, attrCount = 0
START_TAG: name = phone, depth = 2, attrCount = 0
START_TAG: name = company, depth = 3, attrCount = 0
text = Samsung
END_TAG: name = company
START_TAG: name = model, depth = 3, attrCount = 0
text = Galaxy
END_TAG: name = model
START_TAG: name = price, depth = 3, attrCount = 0
text = 18000
END_TAG: name = price
START_TAG: name = screen, depth = 3, attrCount = 2
Attributes: multitouch = yes, resolution = 320x480,
text = 3
END_TAG: name = screen
START_TAG: name = colors, depth = 3, attrCount = 0
START_TAG: name = color, depth = 4, attrCount = 0
text = black
END_TAG: name = color
START_TAG: name = color, depth = 4, attrCount = 0
text = white
END_TAG: name = color
END_TAG: name = colors
END_TAG: name = phone
END_TAG: name = data
END_DOCUMENT

START_DOCUMENT срабатывает два раза по неведомым мне причинам. Далее можно наблюдать, как парсер останавливается в начале каждого тега и дает нам информацию о нем: имя, уровень (глубина), количество атрибутов, имена и названия атрибутов, текст. Также он останавливается в конце тега и мы выводим имя. В конце парсер говорит, что документ закончен END_DOCUMENT.

 

Если xml у вас не в файле, а получен откуда-либо, то XmlPullParser надо создавать другим способом. Перепишем метод prepareXpp:

  XmlPullParser prepareXpp() throws XmlPullParserException {
    // получаем фабрику
    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    // включаем поддержку namespace (по умолчанию выключена)
    factory.setNamespaceAware(true);
    // создаем парсер
    XmlPullParser xpp = factory.newPullParser();
    // даем парсеру на вход Reader
    xpp.setInput(new StringReader(
        "<data><phone><company>Samsung</company></phone></data>"));
    return xpp;
  }

Здесь мы сами создаем парсер с помощью фабрики, включаем поддержку namespace (в нашем случае это не нужно, на всякий случай показываю) и даем парсеру на вход поток из xml-строки (укороченный вариант data.xml).

Все сохраним и запустим. Смотрим лог:

START_DOCUMENT
START_TAG: name = data, depth = 1, attrCount = 0
START_TAG: name = phone, depth = 2, attrCount = 0
START_TAG: name = company, depth = 3, attrCount = 0
text = Samsung
END_TAG: name = company
END_TAG: name = phone
END_TAG: name = data
END_DOCUMENT

Здесь уже START_DOCUMENT сработал один раз, как и должно быть. Ну и далее идут данные элементов документа.


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня




Language

Автор сайта

Дмитрий Виноградов

Подробнее можно посмотреть или почитать.

Никакие другие люди не имеют к этому сайту никакого отношения и просто занимаются плагиатом.

Социальные сети

 

В канале я публикую ссылки на интересные и полезные статьи по Android

В чате можно обсудить вопросы и проблемы, возникающие при разработке



Группа ВКонтакте



Поддержка проекта

Яндекс
410011180491924

WebMoney
R248743991365
Z551306702056

Paypal