В этом уроке мы научимся парсить XML файлы на примере простого приложения для Android. Для начала проведем краткое ознакомление с возможностями обработки XML в Java и посмотрим на стандартные средства Android системы для парсинга XML.
Средства обработки XML в Java
Давайте бегло пробежимся по XML и существующим инструментам. Слово XML означает расширяемый язык разметки, который используется для создания и удобной обработки документов. Для работы с XML в Java есть множество инструментов и библиотек. Давайте рассмотрим некоторые типы парсеров XML файлов:
- SAX парсер
- DOM парсер (создание XML файла, обновление содержимого с помощью DOM и парсинг)
- XMLPull парсеры
DOM Парсер использует подход синтаксического анализа XML-документов в виде древовидной структуры, когда весь XML файл валидируется и загружается в память. Затем начинается разбор документа. Парсинг происходит от исходного узла до конечного узла. В целом этот подход медленнее, чем два следующих.
SAX парсер основан на событиях: в памяти ничего не сохраняется — за счет этого повышается производительность. SAX начинает разбор сверху вниз и не имеет возможности разбирать отдельные узлы. XMLPullParser очень похож на SAX, однако его преимуществом является то, что он может анализировать отдельные узлы.
В Android по умолчанию используется именно XMLPullParser.
Пример использования XMLPullParser в Android
Нам понадобится любой XML файлик с каким-то содержимым, например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="UTF-8"?> <Students> <Student id="1"> <name>Andrey</name> <age>22</age> <language>Java</language> </Student> <Student id="2"> <name>Alex</name> <age>27</age> <language>C++</language> </Student> <Student id="2"> <name>Dima</name> <age>23</age> <language>JavaScript</language> </Student> </Students> |
Этот файлик нам нужно положить в папку assets
. Вам необходимо создать эту папку в проекте Android Studio и создать файлик students.xml с таким содержимым, как показано выше:
Папка assets с файликом students.xml
Теперь подготовим модель, который будет представлять информацию об одном элементе Student:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public class Student { private String name; private int age; private int id; private String language; @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + ", language='" + language + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getLanguage() { return language; } public void setLanguage(String language) { this.language = language; } public int getId() { return id; } public void setId(int id) { this.id = id; } } |
Теперь посмотрим на файл компоновки activity_main.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <TextView android:id="@+id/text_view_info" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout> |
Как видите, он достаточно прост и содержит всего один виджет TextView внутри компонента RelativeLayout.
Следующим шагом будет код для разбора XML файла с помощью XMLPullParser
. Напишем его в прямо MainActivity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
package javadevblog.com.xmlpullparserapp; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.util.Xml; import android.widget.TextView; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import javadevblog.com.xmlpullparserapp.model.Student; public class MainActivity extends AppCompatActivity { public static final String STUDENTS_XML_FILE = "students.xml"; TextView mTextViewInfo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextViewInfo = (TextView) findViewById(R.id.text_view_info); try { // создаем и инициализируем XmlPullParser XmlPullParser parser = createXmlPullParser(STUDENTS_XML_FILE); // парсим xml файл в список объектов Student List<Student> students = parseXML(parser); mTextViewInfo.setText(students.toString()); } catch (XmlPullParserException | IOException e) { e.printStackTrace(); } } @NonNull private XmlPullParser createXmlPullParser(String fileName) throws IOException, XmlPullParserException { XmlPullParser parser = Xml.newPullParser(); // получаем доступ к xml файлу InputStream inputStream = getApplicationContext().getAssets().open(fileName); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setInput(inputStream, null); return parser; } private List<Student> parseXML(XmlPullParser parser) throws XmlPullParserException, IOException { List<Student> students = new ArrayList<>(); // получаем первое событие в xml файле int eventType = parser.getEventType(); Student student = null; // итерационно обходим xml файл пока не наткнемся на тип события 'конец документа' while (eventType != XmlPullParser.END_DOCUMENT) { String name = ""; // обрабатываем события начала документа if (eventType == XmlPullParser.START_DOCUMENT) { students = new ArrayList<>(); // парсим xml файл в список объектов Student } else if (eventType == XmlPullParser.START_TAG) { name = parser.getName(); if (name.equals("Student")) { student = new Student(); String id = parser.getAttributeValue(null, "id"); student.setId(Integer.parseInt(id)); } else if (student != null) { if (name.equals("name")) { String value = parser.nextText(); student.setName(value); } else if (name.equals("age")) { String value = parser.nextText(); student.setAge(Integer.parseInt(value)); } else if (name.equals("language")) { String value = parser.nextText(); student.setLanguage(value); } } // доходим до конца XML файла } else if (eventType == XmlPullParser.END_TAG) { name = parser.getName(); if (name.equalsIgnoreCase("Student") && student != null) { students.add(student); } } // переходим к следующему событию внутри XML eventType = parser.next(); } return students; } } |
Обратите внимание! В коде выше мы использовали модификатор поведения парсера, а именно parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,
false
);
Эта функция определяет, обрабатывает ли анализатор пространств имен.
Пояснение к коду. Как видно из кода выше, мы проходим в while цикле по файлу до события, которое означает конец файла (XmlPullParser.END_DOCUMENT
). В каждой итерации мы указали события, которые нам нужно обрабатывать (XmlPullParser.START_TAG
, XmlPullParser.END_TAG
и т.д.). Мы обрабатываем события и сохраняем нужные нам значения в список ArrayList. Результат разбора печатаем в TextView
виджете.
Результат парсинга XML файла с помощью XMLPullParser
:
Экран приложения с результатами парсинга XML файла с помощью XMLPullParser
Читайте подробнее об обработке XML в Java и Android.
Скачать рабочий Android проект со всеми кодами можно здесь.