Получение xml по сети

Последнее обновление: 18.10.2021

Рассмотрим получение данных в формате xml по сети. Допустим, на некотором сайте https://example.com находится файл 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>

То есть сам файл доступен по адресу https://example.com/users.xml. Но это необязательно должен быть именно файл, это может быть любой ресурс, который динамически генерирует данные в xml.

Возьмем стандартный проект Android и вначале определим в нем класс 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;
    }
}

Далее определим класс UserXmlParser:

package com.example.xmlapp;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import java.util.ArrayList;
import java.io.StringReader;

public class UserXmlParser {

    private ArrayList<User> users;

    public UserXmlParser(){
        users = new ArrayList<>();
    }

    public ArrayList<User> getUsers(){
        return  users;
    }

    public boolean parse(String xmlData){
        boolean status = true;
        User currentUser = null;
        boolean inEntry = false;
        String textValue = "";

        try{
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            factory.setNamespaceAware(true);
            XmlPullParser xpp = factory.newPullParser();

            xpp.setInput(new StringReader(xmlData));
            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 из сети в Android

Для парсинга xml здесь используется класс XmlPullParser, который уже рассматривался в прошлой теме. Единственное отличие заключается в том, что для создания объекта этого класса применяется класс XmlPullParserFactory:

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xpp = factory.newPullParser();

Для работы определим простейший визуальный интефейс в файле activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:id="@+id/contentView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@id/usersList"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <ListView
        android:id="@+id/usersList"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/contentView" />

</androidx.constraintlayout.widget.ConstraintLayout>

Здесь определен элемент TextView для отображения некоторой дополнительной информации о состоянии загрузки файла и элемент ListView для отображения загруженных объектов.

Далее изменим класс MainActivity:

package com.example.xmlapp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		
        ListView usersList = findViewById(R.id.usersList);
        TextView contentView = findViewById(R.id.contentView);
		
        contentView.setText("Загрузка...");
        new Thread(new Runnable() {
            public void run() {
                try{
                    String content = download("https://example.com/users.xml");
                    usersList.post(new Runnable() {
                        public void run() {
                            UserXmlParser parser = new UserXmlParser();
                            if(parser.parse(content))
                            {
                                ArrayAdapter<User> adapter = new ArrayAdapter(getBaseContext(),
                                        android.R.layout.simple_list_item_1, parser.getUsers());
                                usersList.setAdapter(adapter);
                                contentView.setText("Загруженно объектов: " + adapter.getCount());
                            }
                        }
                    });
                }
                catch (IOException ex){
                    contentView.post(new Runnable() {
                        public void run() {
                            contentView.setText("Ошибка: " + ex.getMessage());
                        }
                    });
                }
            }
        }).start();
    }

    private String download(String urlPath) throws IOException{
        StringBuilder xmlResult = new StringBuilder();
        BufferedReader reader = null;
        InputStream stream = null;
        HttpsURLConnection connection = null;
        try {
            URL url = new URL(urlPath);
            connection = (HttpsURLConnection) url.openConnection();
            stream = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(stream));
            String line;
            while ((line=reader.readLine()) != null) {
                xmlResult.append(line);
            }
            return xmlResult.toString();
        } finally {
            if (reader != null) {
                reader.close();
            }
            if (stream != null) {
                stream.close();
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}

При создании MainActivity будет запускаться дополнительный поток, который вызывает метод download(). Этот метод с помощью класса HttpsURLConnection загужает файл users.xml и возвращает его содержимое в виде строки (Если необходимо загрузить файл xml по протоколу http, то вместо применяется класса HttpsURLConnection класс java.net.HttpURLConnection).

String content = download("https://example.com/users.xml");

Затем загруженное содержимое передается в метод parse(), класса UserXmlParser, который формирует список объектов.

UserXmlParser parser = new UserXmlParser();
if(parser.parse(content)){
	//...................

Затем загруженный список передается в адаптер ArrayAdapter, а через него в ListView для отображения на экране устройства:

ArrayAdapter<User> adapter = new ArrayAdapter(getBaseContext(), android.R.layout.simple_list_item_1, parser.getUsers());
usersList.setAdapter(adapter);

В завершении надо добавить в файл манифеста AndroidManifest.xml разрешения на взаимодействие с сетью:

<uses-permission android:name="android.permission.INTERNET"/>

И после запуска приложения в окне Logcat мы увидим полученные с сервера данные:

XmlPullParser и парсинг xml-файла и HttpsURLConnection в Android и Java
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850