Kotlin and SimpleXML - Unable to satisfy ElementList Error

173 views Asked by At

I'm struggling to get simpleXML and Kotlin to read a XML file properly.

I've got the following Root class:

    class ServerConfiguration {   
      @field:Root(strict = false, name = "serverConfiguration")
      @field:ElementList(required = true, name = "channels", entry = "channel", inline = true, type=Channel::class)
      lateinit var channels: List<Channel>
      @field:Element(name = "serverSettings", required = true, type = ServerSettings::class)
      lateinit var serverSettings: ServerSettings
    }

(The Channel class itself has also Lists, but even if I leave it with simple Attributes (ie Strings), it won't work.)

The XML contains:

    <serverConfiguration version="3.5.2">
    <date>2022-07-12 10:57:47</date>
    <channelGroups>
    [... lots of groups]
    </channelGroups>
    <channels>
      <channel version="3.5.2">
        <id>b7cb6bf9-d3a5-4a74-8399-b6689d915a15</id>
        <nextMetaDataId>6</nextMetaDataId>
        <name>cANACR_1_Fhir2Hl7Omg</name>
      <connector class="[...].TcpReceiverProperties" version="3.5.2">
      [... more ]     
      </channel>
      [... a lot of channels]
      </channels>
      [... even more data]
    </serverConfiguration>

Since there are multiple Tags in the xml that contain a "class" Attribute, I understand that I need to use inline = true in my @field:ElementList

I got through a lot of errors up until this point which I could resolve by myself but this one eludes me.

I run the Serializer via:

val serializer: Serializer = Persister()
val dataFetch = serializer.read(ServerConfiguration::class.java, myFile!!, false)

The Error (I cut out classpaths):

org.simpleframework.xml.core.ValueRequiredException: Unable to satisfy @org.simpleframework.xml.ElementList(entry="channel", data=false, inline=true, name="channels", type=Channel.class, required=true, empty=true) on field 'channels' private java.util.List ServerConfiguration.channels for class ServerConfiguration at line 1

If anyone could nudge me in the right direction, I'd be very grateful.

Addendum:

  • If I set required=false the program runs, but not a single channel is read.
  • I've tried ArrayList, List, and Set as datatype
  • I've tried to circumvent lateinit with var channels: List<Channel> = mutableListOf()
1

There are 1 answers

0
K. K. On

I've got it working through adding a wrapper class for the nested lists:

ServerConfiguration.kt:

[...]
 @field:Element(name="channels", required = true, type=ChannelList::class)
    lateinit var channelList: ChannelList

ChannelList.kt:

class ChannelList {

    @field:ElementList(required = true,  inline = true,name = "channels", entry = "channel", type=Channel::class, data = true, empty=false)
    var channels: List<Channel> = mutableListOf()

}

And finally Channel.kt:

class Channel {

    @field:Element(name = "destinationConnectors", required = true, type = DestinationConnectorList::class)
    lateinit var destinationConnectorList: DestinationConnectorList
    @field:Element(name = "exportData", required = true, type=ExportData::class)
    lateinit var exportData: ExportData
[...]

While this is working, I would have expected simpleXML to be able to add the Elements of the List directly without needing to use a wrapper class (ChannelList). If anyone knows how to achieve this, please feel free to comment or add your solution.

Kind regards, K