Home > Back-end >  Android kotlin SimpleXmlConverterFactory crashes when reading attributes
Android kotlin SimpleXmlConverterFactory crashes when reading attributes

Time:12-03

I'm traying to parse XML with Retrofit2 and SimpleXmlConverterFactory, that's working until I tried to read attributes of a node, there, it crashes with no log.

My XML :

<HotelSearchRES>
  <Destination id="1">Tunisie</Destination>
  <City id="104">Hammamet</City>
  <Currency>1</Currency>
  <Language>1</Language>
  <FromDate>01/12/2021</FromDate>
  <ToDate>02/12/2021</ToDate>
</HotelSearchRES>

My Classes :

@Root(name = "HotelSearchRES", strict = false)
class SearchResultsWrapper @JvmOverloads constructor() {
    @Element(name = "Destination")
    var destination: Destination? = null

    @set:Element(name = "City")
    @get:Element(name = "City")
    var city: String? = null


    @set: Element(name = "Currency")
    @get: Element(name = "Currency")
    var currency: Int? = null

    @set: Element(name = "Language")
    @get: Element(name = "Language")
    var language: Int? = null

    @set: Element(name = "FromDate")
    @get: Element(name = "FromDate")
    var fromDate: String? = null

    @set: Element(name = "ToDate")
    @get: Element(name = "ToDate")
    var toDate: String? = null

}

class Destination(){
    @Attribute(required = false)
    val id: String? = null

    @Text(required = false)
    val destination: String? = null
}

The problem seams related to attribute reading, so if I remove the first line everything works :

@Element(name = "Destination")
    var destination: Destination? = null

Any help would be appreciated ;)

CodePudding user response:

In Kotlin, a field is only used as a part of a property to hold its value in memory. Fields cannot be declared directly. However, when a property needs a backing field, Kotlin provides it automatically. This backing field can be referenced in the accessors using the field identifier

Do something like:

 @field:Element(name = "Destination")
 var destination: Destination? = null

By the way you don't need to do the @get, @set on your properties, you can use the @field

See this or here Annotations for detailed answers

CodePudding user response:

Ok, for those who are messing with parsing attributes, here are the correct class annotations :

@Root(name = "HotelSearchRES", strict = false)
class HotelSearchRES @JvmOverloads constructor(){
    @field:Element(name = "Destination") var destination: Destination? = null
    @field:Element(name = "City") var city: City? = null
    @field:Element(name = "Currency") var currency: Int = 0
    @field:Element(name = "Language") var language: Int = 0
    @field:Element(name = "FromDate") var fromDate: String? = null
    @field:Element(name = "ToDate") var toDate: String? = null

}

@Root(name = "Destination", strict = false)
class Destination {
    @field:Attribute(name = "id", required = false) var id: Int = 0
    @field:Text var text: String? = null
}

@Root(name = "City", strict = false)
class City {
    @field:Attribute(name = "id", required = false) var id: Int = 0
    @field:Text var text: String? = null
}

Thank you @MG1616 for the trick

  • Related