3 способа анализа и чтения XML файлов с Kotlin Android

Документ XML обычно используется для обмена данными в Интернете. Данные, представленные в формате XML, могут часто обновляться, и их анализ — обычная задача для сетевых приложений.

Существует три типа синтаксических анализаторов для парсинга XML-данных и чтения их в приложениях Android в Kotlin:

  1. DOM Parser
  2. SAX Parser
  3. XMLPullParser

DOM Parser

Анализатор Android DOM (Document Object Model) использует объектно-ориентированный подход для создания и анализа XML-файлов в приложениях для Android. Анализатор DOM загружает XML-файл в память для анализа XML-документа. По этой причине он потребляет больше памяти.

Пример синтаксического анализа XML с использованием DOM Parser

В этом примере мы анализируем XML-данные и отображаем их в ListView.

Activity_main.xml

Добавьте ListView в макет activity_main.xml.

 
<?xml version="1.0" encoding="utf-8"?>  
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:app="http://schemas.android.com/apk/res-auto"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context="example.javatpoint.com.kotlinxmlparsingusingdomparser.MainActivity">  
  
    <ListView  
            android:id="@+id/listView"  
            android:layout_width="match_parent"  
            android:layout_height="match_parent">  
     </ListView>  
</android.support.constraint.ConstraintLayout>

empdetail.xml

Создайте XML-документ empdetail.xml в каталоге ресурсов, чтобы проанализировать данные с помощью синтаксического анализатора DOM.

<?xml version="1.0" encoding="utf-8"?>  
<records>  
    <employee>  
        <name>Sachin Kumar</name>  
        <salary>50000</salary>  
        <designation>Developer</designation>  
    </employee>  
    <employee>  
        <name>Rahul Kumar</name>  
        <salary>60000</salary>  
        <designation>Team Leader</designation>  
    </employee>  
    <employee>  
        <name>John Mike</name>  
        <salary>70000</salary>  
        <designation>Manager</designation>  
    </employee>  
    <employee>  
        <name>Ajay Kumar</name>  
        <salary>45000</salary>  
        <designation>Developer</designation>  
    </employee>  
    <employee>  
        <name>Toni Nayer</name>  
        <salary>55000</salary>  
        <designation>Marketing</designation>  
    </employee>  
    <employee>  
        <name>Mr Bony</name>  
        <salary>42000</salary>  
        <designation>Sales</designation>  
    </employee>  
    <employee>  
        <name>Raj Kumar</name>  
        <salary>30000</salary>  
        <designation>Production</designation>  
    </employee>  
    <employee>  
        <name>Rahul Kumar</name>  
        <salary>60000</salary>  
        <designation>Team Leader</designation>  
    </employee>  
    <employee>  
        <name>John Mike</name>  
        <salary>70000</salary>  
        <designation>Manager</designation>  
    </employee>  
    <employee>  
        <name>Sachin Kumar</name>  
        <salary>50000</salary>  
        <designation>Developer</designation>  
    </employee>  
    <employee>  
        <name>Rahul Kumar</name>  
        <salary>60000</salary>  
        <designation>Team Leader</designation>  
    </employee>  
    <employee>  
        <name>John Mike</name>  
        <salary>70000</salary>  
        <designation>Manager</designation>  
    </employee>  
</records>

custom_list.xml

Создайте собственный макет для отображения списка данных в ListView.

 <?xml version="1.0" encoding="utf-8"?>  
<LinearLayout 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"  
    android:orientation="horizontal">  
    <LinearLayout  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_weight="1"  
        android:orientation="vertical">  
  
        <TextView  
            android:id="@+id/name"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:text="name"  
            android:textStyle="bold"  
            android:layout_marginLeft="15dp"  
            android:layout_marginStart="15dp"  
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />  
  
        <TextView  
            android:id="@+id/salary"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:text="salary"  
            android:layout_marginLeft="15dp"  
            android:layout_marginStart="15dp"  
            android:layout_marginTop="5dp"  
            android:textSize="16sp"/>  
        <TextView  
            android:id="@+id/designation"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:text="designation"  
            android:layout_marginLeft="15dp"  
            android:layout_marginStart="15dp"  
            android:layout_marginTop="5dp"  
            android:textSize="16sp"/>  
    </LinearLayout>  
</LinearLayout>    

MainActivity.kt

Добавьте следующий код для чтения и анализа XML-данных с помощью синтаксического анализатора DOM. Создайте экземпляр объектов DocumentBuilderFactory, DocumentBuilder и Document.

HashMap используется для чтения данных из XML-документа и добавления их в ArrayList().

 
package example.javatpoint.com.kotlinxmlparsingusingdomparser 
 
import android.support.v7.app.AppCompatActivity 
import android.os.Bundle 
import android.widget.ListView 
import android.widget.SimpleAdapter 
import org.w3c.dom.Element 
import org.w3c.dom.Node 
import org.xml.sax.SAXException 
import java.io.IOException 
import javax.xml.parsers.DocumentBuilderFactory 
import javax.xml.parsers.ParserConfigurationException 
 
class MainActivity : AppCompatActivity() { 
    var empDataHashMap = HashMap() 
    var empList: ArrayList<HashMap> = ArrayList() 
    override fun onCreate(savedInstanceState: Bundle?) { 
        super.onCreate(savedInstanceState) 
        setContentView(R.layout.activity_main) 
        try { 
            val lv = findViewById(R.id.listView) 
            val istream = assets.open("empdetail.xml") 
            val builderFactory = DocumentBuilderFactory.newInstance() 
            val docBuilder = builderFactory.newDocumentBuilder() 
            val doc = docBuilder.parse(istream) 
 //reading the tag "employee" of empdetail file 
            val nList = doc.getElementsByTagName("employee") 
            for(i in 0 until nList.getLength()) { 
                if(nList.item(0).getNodeType().equals(Node.ELEMENT_NODE) ) { 
               //creating instance of HashMap to put the data of node value          
    empDataHashMap = HashMap() 
                    val element = nList.item(i) as Element 
                    empDataHashMap.put("name", getNodeValue("name", element)) 
                    empDataHashMap.put("salary", getNodeValue("salary", element)) 
                    empDataHashMap.put("designation", getNodeValue("designation", element)) 
   //adding the HashMap data to ArrayList 
                    empList.add(empDataHashMap) 
                } 
            } 
            val adapter = SimpleAdapter(this@MainActivity, empList, R.layout.custom_list, arrayOf("name", "salary", "designation"), intArrayOf(R.id.name, R.id.salary, R.id.designation)) 
            lv.setAdapter(adapter) 
        } catch(e: IOException) { 
            e.printStackTrace() 
        } catch(e: ParserConfigurationException) { 
            e.printStackTrace() 
        } catch(e: SAXException) { 
            e.printStackTrace() 
        } 
 
    } 
    // function to return node value 
    protected fun getNodeValue(tag: String, element: Element): String { 
        val nodeList = element.getElementsByTagName(tag) 
        val node = nodeList.item(0) 
        if(node != null) { 
            if(node.hasChildNodes()) { 
                val child = node.getFirstChild() 
                while(child != null) { 
                    if(child.getNodeType() === Node.TEXT_NODE) { 
                        return child.getNodeValue() 
                    } 
                } 
            } 
        } 
        return "" 
    } 
} 

Выход:

DOM Parser

SAX Parser

В Android широко используется SAX(Simple API for XML) для анализа XML. Синтаксический анализатор SAX проверяет XML-документ посимвольно и преобразует его в серию событий, таких как startElement(), endElement() и character(). Чтобы читать и анализировать данные XML с помощью анализатора SAX, нам нужно создать экземпляр объектов SAXParserFactory, SAXParser и DefaultHandler в приложениях Android с помощью Котлин.

Пример разбора XML с использованием SAX Parser

В этом примере мы будем анализировать данные XML с помощью синтаксического анализатора SAX и отображать их в ListView.

Activity_main.xml

Добавьте ListView в макет activity_main.xml.

 
<?xml version="1.0" encoding="utf-8"?>  
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:app="http://schemas.android.com/apk/res-auto"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context="example.javatpoint.com.kotlinxmlparsingusingsaxparser.MainActivity">  
  
   <ListView  
        android:id="@+id/listView"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent">  
    </ListView>  
  
</android.support.constraint.ConstraintLayout>

empdetail.xml

Создайте XML-документ empdetail.xml в каталоге ресурсов для анализа данных с помощью синтаксического анализатора SAX.

  <?xml version="1.0" encoding="utf-8"?>  
<records>  
    <employee>  
        <name>Sachin Kumar</name>  
        <salary>50000</salary>  
        <designation>Developer</designation>  
    </employee>  
    <employee>  
        <name>Rahul Kumar</name>  
        <salary>60000</salary>  
        <designation>Team Leader</designation>  
    </employee>  
    <employee>  
        <name>John Mike</name>  
        <salary>70000</salary>  
        <designation>Manager</designation>  
    </employee>  
    <employee>  
        <name>Ajay Kumar</name>  
        <salary>45000</salary>  
        <designation>Developer</designation>  
    </employee>  
    <employee>  
        <name>Toni Nayer</name>  
        <salary>55000</salary>  
        <designation>Marketing</designation>  
    </employee>  
    <employee>  
        <name>Mr Bony</name>  
        <salary>42000</salary>  
        <designation>Sales</designation>  
    </employee>  
    <employee>  
        <name>Raj Kumar</name>  
        <salary>30000</salary>  
        <designation>Production</designation>  
    </employee>  
    <employee>  
        <name>Rahul Kumar</name>  
        <salary>60000</salary>  
        <designation>Team Leader</designation>  
    </employee>  
    <employee>  
        <name>John Mike</name>  
        <salary>70000</salary>  
        <designation>Manager</designation>  
    </employee>  
    <employee>  
        <name>Sachin Kumar</name>  
        <salary>50000</salary>  
        <designation>Developer</designation>  
    </employee>  
    <employee>  
        <name>Rahul Kumar</name>  
        <salary>60000</salary>  
        <designation>Team Leader</designation>  
    </employee>  
    <employee>  
        <name>John Mike</name>  
        <salary>70000</salary>  
        <designation>Manager</designation>  
    </employee>  
</records> 

custom_list.xml

Создайте собственный макет для отображения списка данных в ListView.

 <?xml version="1.0" encoding="utf-8"?>  
<LinearLayout 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"  
    android:orientation="horizontal">  
        <LinearLayout  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:layout_weight="1"  
            android:orientation="vertical">  
  
            <TextView  
                android:id="@+id/name"  
                android:layout_width="match_parent"  
                android:layout_height="wrap_content"  
                android:text="name"  
                android:textStyle="bold"  
                android:layout_marginLeft="15dp"  
                android:layout_marginStart="15dp"  
                android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />  
  
            <TextView  
                android:id="@+id/salary"  
                android:layout_width="match_parent"  
                android:layout_height="wrap_content"  
                android:text="salary"  
                android:layout_marginLeft="15dp"  
                android:layout_marginStart="15dp"  
                android:layout_marginTop="5dp"  
                android:textSize="16sp"/>  
            <TextView  
                android:id="@+id/designation"  
                android:layout_width="match_parent"  
                android:layout_height="wrap_content"  
                android:text="designation"  
                android:layout_marginLeft="15dp"  
                android:layout_marginStart="15dp"  
                android:layout_marginTop="5dp"  
                android:textSize="16sp"/>  
        </LinearLayout>  
</LinearLayout>

MainActivity.kt

Добавьте следующий код для чтения и анализа XML-данных с помощью синтаксического анализатора SAX. Создайте экземпляр объектов SAXParserFactory, SAXParser и DefaultHandler.

HashMap используется для чтения данных из XML-документа и добавления их в ArrayList().

 
package example.javatpoint.com.kotlinxmlparsingusingsaxparser 
 
import android.support.v7.app.AppCompatActivity 
import android.os.Bundle 
import org.xml.sax.helpers.DefaultHandler 
import javax.xml.parsers.SAXParserFactory 
import android.widget.ListView 
import android.widget.SimpleAdapter 
import org.xml.sax.SAXException 
import java.io.IOException 
import java.util.ArrayList 
import java.util.HashMap 
import javax.xml.parsers.ParserConfigurationException 
import javax.xml.parsers.SAXParser 
 
class MainActivity : AppCompatActivity() { 
    internal var empList = ArrayList<HashMap>() 
    internal var empData = HashMap() 
    override fun onCreate(savedInstanceState: Bundle?) { 
        super.onCreate(savedInstanceState) 
        setContentView(R.layout.activity_main) 
        val lv:ListView = findViewById(R.id.listView) 
        try { 
                        //instancing the SAXParserFactory class 
            val parserFactory:SAXParserFactory = SAXParserFactory.newInstance() 
            //instancing the SAXParser class 
            val saxParser:SAXParser = parserFactory.newSAXParser() 
            val defaultHandler= object : DefaultHandler() { 
                var currentValue = "" 
                var currentElement = false 
                //overriding the startElement() method of DefaultHandler 
                override fun startElement(uri: String, localName: String, qName: String, attributes: org.xml.sax.Attributes) { 
                    currentElement = true 
                    currentValue = "" 
                    if(localName == "employee") { 
                        empData = HashMap() 
                    } 
                } 
                //overriding the endElement() method of DefaultHandler 
                override fun endElement(uri: String, localName: String, qName: String) { 
                    currentElement = false 
                    if(localName.equals("name", ignoreCase = true)) 
                        empData["name"] = currentValue 
                    else if(localName.equals("salary", ignoreCase = true)) 
                        empData["salary"] = currentValue 
                    else if(localName.equals("designation", ignoreCase = true)) 
                        empData["designation"] = currentValue 
                    else if(localName.equals("employee", ignoreCase = true)) 
                        empList.add(empData) 
                } 
                //overriding the characters() method of DefaultHandler 
                override fun characters(ch: CharArray, start: Int, length: Int) { 
                    if(currentElement) { 
                        currentValue = currentValue + String(ch, start, length) 
                    } 
                } 
            } 
            val istream = assets.open("empdetail.xml") 
            saxParser.parse(istream, defaultHandler) 
            //creating Adapter class to access the custom list 
            val adapter = SimpleAdapter(this@MainActivity, empList, R.layout.custom_list, arrayOf("name", "salary", "designation"), intArrayOf(R.id.name, R.id.salary, R.id.designation)) 
            lv.adapter = adapter 
        } catch(e: IOException) { 
            e.printStackTrace() 
        } catch(e: ParserConfigurationException) { 
            e.printStackTrace() 
        } catch(e: SAXException) { 
            e.printStackTrace() 
        } 
 
    } 
} 

Вывод:

SAX Parser

XMLPullParser

Android рекомендует использовать XMLPullParser для разбора файла XML, а не SAX и DOM, потому что это быстро.

Интерфейс org.xmlpull.v1.XmlPullParser предоставляет функциональные возможности для анализа XML-документа с помощью XMLPullParser.

События XmlPullParser

Метод next() класса XMLPullParser перемещает указатель курсора на следующее событие. Как правило, мы используем четыре константы (работает как событие), определенные в интерфейсе XMLPullParser.

  1. START_TAG: будет прочитан начальный тег XML.
  2. TEXT: текстовое содержимое было прочитано, текстовое содержимое можно получить с помощью метода getText().
  3. END_TAG: будет прочитан конечный тег.
  4. END_DOCUMENT: больше нет доступных событий.

Пример разбора XML с использованием XMLPullParser

В этом примере мы читаем XML-данные и привязываем их к ListView с помощью XMLPullParser.

Activity_main.xml

Добавьте ListView в макет activity_main.xml.

 <?xml version="1.0" encoding="utf-8"?>  
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:app="http://schemas.android.com/apk/res-auto"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context="example.javatpoint.com.kotlinxmlparsingusingxmlpullparser.MainActivity">  
  
    <ListView  
        android:id="@+id/listView"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content" >  
  
    </ListView>  
  
</android.support.constraint.ConstraintLayout>

employees.xml

Создайте XML-документ employee.xml в каталоге ресурсов для анализа данных с помощью XMLPullParser.

<?xml version="1.0" encoding="UTF-8"?>  
<employees>  
    <employee>  
        <id>1</id>  
        <name>Sachin Kumar</name>  
        <salary>50000</salary>  
    </employee>  
    <employee>  
        <id>2</id>  
        <name>Rahul Kumar</name>  
        <salary>60000</salary>  
    </employee>  
    <employee>  
        <id>3</id>  
        <name>John Mike</name>  
        <salary>70000</salary>  
    </employee>  
    <employee>  
        <id>4</id>  
        <name>Ajay Kumar</name>  
        <salary>45000</salary>  
    </employee>  
    <employee>  
        <id>5</id>  
        <name>Toni Nayer</name>  
        <salary>55000</salary>  
    </employee>  
    <employee>  
        <id>6</id>  
        <name>Mr Bony</name>  
        <salary>42000</salary>  
    </employee>  
    <employee>  
        <id>7</id>  
        <name>Raj Kumar</name>  
        <salary>30000</salary>  
    </employee>  
    <employee>  
        <id>8</id>  
        <name>Rahul Kumar</name>  
        <salary>60000</salary>  
    </employee>  
    <employee>  
        <id>9</id>  
        <name>John Mike</name>  
        <salary>70000</salary>  
    </employee>  
    <employee>  
        <id>10</id>  
        <name>Sachin Kumar</name>  
        <salary>50000</salary>  
    </employee>  
    <employee>  
        <id>11</id>  
        <name>Rahul Kumar</name>  
        <salary>60000</salary>  
    </employee>  
    <employee>  
        <id>12</id>  
        <name>John Mike</name>  
        <salary>70000</salary>  
    </employee>  
</employees>   

Employee.kt

Создайте класс модели данных Employee.kt, соответствующий файлу данных XML.

 
package example.javatpoint.com.kotlinxmlparsingusingxmlpullparser 
 
class Employee { 
    var id: Int = 0 
    var name: String? = null 
    var salary: Float = 0.toFloat() 
 
    override fun toString(): String { 
        return " Id = $id\n Name = $name\n Salary = $salary" 
    } 
} 

XmlPullParserHandler.kt

Напишите код для анализа XML-файла с помощью XMLPullParser. В этом классе мы возвращаем всех сотрудников в списке.

 
package example.javatpoint.com.kotlinxmlparsingusingxmlpullparser 
 
import org.xmlpull.v1.XmlPullParserException 
import org.xmlpull.v1.XmlPullParser 
import org.xmlpull.v1.XmlPullParserFactory 
import java.io.IOException 
import java.io.InputStream 
 
class XmlPullParserHandler { 
    private val employees = ArrayList() 
    private var employee: Employee? = null 
    private var text: String? = null 
 
    fun parse(inputStream: InputStream): List { 
        try { 
            val factory = XmlPullParserFactory.newInstance() 
            factory.isNamespaceAware = true 
            val parser = factory.newPullParser() 
            parser.setInput(inputStream, null) 
            var eventType = parser.eventType 
            while(eventType != XmlPullParser.END_DOCUMENT) { 
                val tagname = parser.name 
                when(eventType) { 
                    XmlPullParser.START_TAG -> if(tagname.equals("employee", ignoreCase = true)) { 
                        // create a new instance of employee 
                        employee = Employee() 
                    } 
                    XmlPullParser.TEXT -> text = parser.text 
                    XmlPullParser.END_TAG -> if(tagname.equals("employee", ignoreCase = true)) { 
                        // add employee object to list 
                        employee?.let { employees.add(it) } 
                    } else if(tagname.equals("id", ignoreCase = true)) { 
                        employee!!.id = Integer.parseInt(text) 
                    } else if(tagname.equals("name", ignoreCase = true)) { 
                        employee!!.name = text 
                    } else if(tagname.equals("salary", ignoreCase = true)) { 
                        employee!!.salary = java.lang.Float.parseFloat(text) 
                    } 
 
                    else -> { 
                    } 
                } 
                eventType = parser.next() 
            } 
 
        } catch(e: XmlPullParserException) { 
            e.printStackTrace() 
        } catch(e: IOException) { 
            e.printStackTrace() 
        } 
        return employees 
    } 
} 

MainActivity.kt

В этом классе мы отправляем XML-данные в ArrayAdapter и привязываем их к ListView.

 
package example.javatpoint.com.kotlinxmlparsingusingxmlpullparser 
 
import android.support.v7.app.AppCompatActivity 
import android.os.Bundle 
import android.widget.ArrayAdapter 
import android.widget.ListView 
import java.io.IOException  
 
 
class MainActivity : AppCompatActivity() { 
 
    override fun onCreate(savedInstanceState: Bundle?) { 
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main) 
        val listView = findViewById(R.id.listView) 
        var employees: List? = null  
        try { 
            val parser = XmlPullParserHandler() 
            val istream = assets.open("employees.xml") 
            employees = parser.parse(istream) 
 
            val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, employees) 
            listView.adapter = adapter 
 
        } catch(e: IOException) { 
            e.printStackTrace() 
        } 
    } 
} 

Выход:

Kotlin Android XMLPullParser - вывод

Оцените статью