Одним из распространенных форматов хранения и передачи данных является xml. Рассмотрим, как с ним работать в приложении на Android.
Приложение может получать данные в формате xml различными способами - из ресурсов, из сети и т.д. В данном случае рассмотрим ситуацию, когда файл xml хранится в ресурсах.
Возьмем стандартный проект Android по умолчанию и в папке res создадим каталог xml. Для этого нажмем на каталог res правой кнопкой мыши и в контекстном меню выберем New -> Android Resource Directory:
В появившемся окне в качестве типа ресурсов укажем xml:
В этот каталог добавим новый файл, который назовем users.xml и который будет иметь следующее содержимое:
<?xml version="1.0" encoding="utf-8"?>
<users>
<user>
<name>Tom</name>
<age>36</age>
</user>
<user>
<name>Alice</name>
<age>32</age>
</user>
<user>
<name>Bob</name>
<age>28</age>
</user>
</users>
Это обычный файл xml, который хранит набор элементов user. Каждый элемент характеризуется наличием двух подэлементов - name и age. Условно говоря, каждый элемент описывает пользователя, у которого есть имя и возраст.
В папку, где находится основной класс MainActivity, добавим новый класс, который назовем User:
package com.example.xmlapp;
public class User {
private String name;
private String age;
public String getName(){
return name;
}
public String getAge(){
return age;
}
public void setName(String name){
this.name = name;
}
public void setAge(String age){
this.age = age;
}
public String toString(){
return "User: " + name + " - " + age;
}
}
Этот класс описывает товар, информация о котором будет извлекаться из xml-файла.
И в ту же папку добавим новый класс UserResourceParser:
Определим для класса UserResourceParser следующий код:
package com.example.xmlapp;
import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
public class UserResourceParser {
private ArrayList<User> users;
public UserResourceParser(){
users = new ArrayList<>();
}
public ArrayList<User> getUsers(){
return users;
}
public boolean parse(XmlPullParser xpp){
boolean status = true;
User currentUser = null;
boolean inEntry = false;
String textValue = "";
try{
int eventType = xpp.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
String tagName = xpp.getName();
switch (eventType){
case XmlPullParser.START_TAG:
if("user".equalsIgnoreCase(tagName)){
inEntry = true;
currentUser = new User();
}
break;
case XmlPullParser.TEXT:
textValue = xpp.getText();
break;
case XmlPullParser.END_TAG:
if(inEntry){
if("user".equalsIgnoreCase(tagName)){
users.add(currentUser);
inEntry = false;
} else if("name".equalsIgnoreCase(tagName)){
currentUser.setName(textValue);
} else if("age".equalsIgnoreCase(tagName)){
currentUser.setAge(textValue);
}
}
break;
default:
}
eventType = xpp.next();
}
}
catch (Exception e){
status = false;
e.printStackTrace();
}
return status;
}
}
Данный класс выполняет функции парсинга xml. Распарсенные данные будут храниться в переменной users. Непосредственно сам парсинг осуществляется
с помощью функции parse. Основную работу выполняет передаваемый в качестве параметра объект XmlPullParser. Этот
класс позволяет пробежаться по всему документу xml и получить его содержимое.
Когда данный объект проходит по документу xml, при обнаружении определенного тега он генерирует некоторое событие. Есть четыре события, которые описываются следующими константами:
START_TAG: открывающий тег элемента
TEXT: прочитан текст элемента
END_TAG: закрывающий тег элемента
END_DOCUMENT: конец документа
С помощью метода getEventType() можно получить первое событие и потом последовательно считывать документ, пока не дойдем до его конца.
Когда будет достигнут конец документа, то событие будет представлять константу END_DOCUMENT:
int eventType = xpp.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
//......................
eventType = xpp.next();
}
Для перехода к следующему событию применяется метод next().
При чтении документа с помощью метода getName() можно получить название считываемого элемента.
String tagName = xpp.getName();
И в зависимости от названия тега и события мы можем выполнить определенные действия. Например, если это открывающий тег элемента user, то создаем новый объект User и устанавливаем, что мы находимся внутри элемента user:
case XmlPullParser.START_TAG:
if("user".equalsIgnoreCase(tagName)){
inEntry = true;
currentUser = new User();
}
break;
Если событие TEXT, то считано содержимое элемента, которое мы можем прочитать с помощью метода getText():
case XmlPullParser.TEXT: textValue = xpp.getText(); break;
Если закрывающий тег, то все зависит от того, какой элемент прочитан. Если прочитан элемент user, то добавляем объект User в коллекцию ArrayList и сбрываем переменную inEntry, указывая, что мы вышли из элемента user:
case XmlPullParser.END_TAG:
if(inEntry){
if("user".equalsIgnoreCase(tagName)){
users.add(currentUser);
inEntry = false;
Если прочитаны элементы name и age, то передаем их значения переменным name и age объекта User:
else if("name".equalsIgnoreCase(tagName)){
currentUser.setName(textValue);
} else if("age".equalsIgnoreCase(tagName)){
currentUser.setAge(textValue);
}
Теперь изменим класс MainActivity, который будет загружать ресурс xml:
package com.example.xmlapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
XmlPullParser xpp = getResources().getXml(R.xml.users);
UserResourceParser parser = new UserResourceParser();
if(parser.parse(xpp))
{
for(User prod: parser.getUsers()){
Log.d("XML", prod.toString());
}
}
}
}
Вначале получаем ресурс xml с помощью метода getXml(), в который передается название ресурса. Данный метод возвращает объект XmlPullParser, который затем используется для парсинга. Для простоты просто выводим данные в окне Logcat: