XMLCoder icon indicating copy to clipboard operation
XMLCoder copied to clipboard

Adding all elements with same prefix to their own struct.

Open jubishop opened this issue 1 year ago • 1 comments

say I have this xml:

  <channel>
    <title>The Changelog: Software Development, Open Source</title>
    <itunes:summary>Software&apos;s best weekly news brief, deep technical interviews &amp; talk show.</itunes:summary>
    <itunes:author>Changelog Media</itunes:author>
 </channel>

which is a stripped down example from the real world of parsing Podcast RSS Feeds :)

It'd be great if I could decode that into something like:

struct Channel: Codable {
 let title:String
 
 struct iTunes: Codable {
   let summary: String
   let author: String
 }
}

I know I can store all three values in a single flat Channel structure given what's in the Readme, but is there any advanced way to cause this deeper structuring, putting the elements prefixed with iTunes: into the nested iTunes struct?

Right now my flattened version looks like this:

  struct Channel: Codable {
    let title: String
    let itunesSummary: String?
    let itunesAuthor: String?

    enum CodingKeys: String, CodingKey {
      case title
      case itunesSummary = "itunes:summary"
      case itunesAuthor = "itunes:author"
    }
  }

jubishop avatar Jan 01 '25 21:01 jubishop

I can, of course, implement my own init(from: decoder) method, which looks something like this for me right now:

  struct Channel: Decodable {
    let title: String
    let iTunes: iTunesNamespace

    enum CodingKeys: String, CodingKey {
      case title
    }

    struct iTunesNamespace: Decodable {
      let summary: String?
      let author: String?

      enum CodingKeys: String, CodingKey {
        case summary = "itunes:summary"
        case author = "itunes:author"
      }
    }
    
    init(from decoder: Decoder) throws {
      let container = try decoder.container(keyedBy: CodingKeys.self)
      title = try container.decode(String.self, forKey: .title)
      iTunes = try iTunesNamespace.init(from: decoder)
    }
  }

this just gets to be a little verbose. any ideas on how to shorten would be appreciated!

jubishop avatar Jan 01 '25 21:01 jubishop