XML десериализация Android kotlin

Нужно распарсить полученные строковые данные в формате XML в kotlin (Android). Сталкивался ли кто с такой задачей? в большинстве примерах парсят данные в формате json, но по некоторым причинам не нельзя поменять формат. В java Spring приложении использовал для этих целей JAXBContext, но здесь я так понимаю он не доступен.

Добавлено:

пример данных

<Worker>
    <currentRequestId>2</currentRequestId>
    <status>0</status>
    <firstname>Хайнц</firstname>
    <lastName>Фуфелшмертц</lastName>
    <order>
        <orderId>1</orderId>
        <time>768675597</time>
        <deliveryStatus>2</deliveryStatus>
        <item>
            <name>name1</name>
            <count>12</count>
        </item>
        <item>
            <name>name2</name>
            <count>12</count>
        </item>
    </order>
    <order>
        <orderId>2</orderId>
        <time>768675597</time>
        <deliveryStatus>1</deliveryStatus>
        <item>
            <name>name3</name>
            <count>7</count>
        </item>
        <item>
            <name>name4</name>
            <count>16</count>
        </item>
    </order>
</Worker>

Ответы (1 шт):

Автор решения: Vadik

Пусть у нас есть data-классы Worker и Order, для простоты примера будем парсить только id и status, при необходимости можно добавить и остальные параметры:

data class Worker(val id: String, val status: String, val orders: List<Order>)
data class Order(val id: String, val status: String)

Создаем XmlPullParser и передаем ему контент с XML:

val content = "<Worker>...</Worker>"
val parser = Xml.newPullParser().also {
    it.setInput(content.reader())
}

Адаптируем пример из тренинга и получим такой код:

private fun readWorker(parser: XmlPullParser): Worker {
    parser.nextTag()
    parser.require(START_TAG, ns, "Worker")
    val orders = mutableListOf<Order>()
    var id = ""
    var status = ""
    while (parser.next() != END_TAG) {
        if (parser.eventType == START_TAG) {
            when (parser.name) {
                "currentRequestId" -> id = readTag(parser)
                "status" -> status = readTag(parser)
                "order" -> orders.add(readOrder(parser))
                else -> skip(parser)
            }
        }
    }
    return Worker(id, status, orders)
}

private fun readOrder(parser: XmlPullParser): Order {
    parser.require(START_TAG, ns, "order")
    var id = ""
    var status = ""
    while (parser.next() != END_TAG) {
        if (parser.eventType == START_TAG) {
            when (parser.name) {
                "orderId" -> id = readTag(parser)
                "deliveryStatus" -> status = readTag(parser)
                else -> skip(parser)
            }
        }
    }
    return Order(id, status)
}

private fun readTag(parser: XmlPullParser): String {
    parser.require(START_TAG, ns, parser.name)
    var result = ""
    if (parser.next() == XmlPullParser.TEXT) {
        result = parser.text
        parser.nextTag()
    }
    parser.require(END_TAG, ns, parser.name)
    return result
}

private fun skip(parser: XmlPullParser) {
    if (parser.eventType == START_TAG) {
        var depth = 1
        while (depth != 0) {
            when (parser.next()) {
                END_TAG -> depth--
                START_TAG -> depth++
            }
        }
    }
}

На выходе получится такой объект Worker:

Worker(
  id=2,
  status=0,
  orders=[
    Order(id=1, status=2),
    Order(id=2, status=1)
  ]
)
→ Ссылка