CoreOffice / XMLCoder

Easy XML parsing using Codable protocols in Swift
https://coreoffice.github.io/XMLCoder/
MIT License
801 stars 112 forks source link

Fix nested attributed intrinsic #78

Closed MaxDesiatov closed 5 years ago

MaxDesiatov commented 5 years ago

As reported in #12 by @thecb4:

A standalone XML element with attributed intrinsic works. When it's embedded in another element, it fails.

// This passes
  let previewTime = 
  """
  <?xml version="1.0" encoding="UTF-8"?>
  <preview_image_time format="24/999 1000/nonDrop">00:00:17:01</preview_image_time>
  """.data(using: .utf8)!

  let decoder = XMLDecoder()
  decoder.errorContextLength = 10

  let metadata1 = try decoder.decode(PreviewImageTime.self, from: previewTime)
  print(metadata1)

// this does not pass
  let preview = 
  """
  <?xml version="1.0" encoding="UTF-8"?>
  <app_preview display_target="iOS-6.5-in" position="1">
    <preview_image_time format="24/999 1000/nonDrop">00:00:17:01</preview_image_time>
  </app_preview>
  """.data(using: .utf8)!

  let metadata2 = try decoder.decode(AppPreview.self, from: preview)
  print(metadata2)

structs:

struct AppPreview: Codable {
  var displayTarget: String
  var position: Int
  var previewImageTime: PreviewImageTime
  // var dataFile: DataFile

  enum CodingKeys: String, CodingKey {
    case displayTarget = "display_target"
    case position
    case previewImageTime = "preview_image_time"
    // case dataFile = "data_file"
  }
}

struct PreviewImageTime: Codable, DynamicNodeEncoding {

  var format: String
  var value: String

  enum CodingKeys: String, CodingKey {
    case format
    case value
  }

  static func nodeEncoding(forKey key: CodingKey) -> XMLEncoder.NodeEncoding {
    print("node encoding")
    switch key {
      case CodingKeys.format:
        return .attribute
      default:
        return .element
    }
  }
}
MaxDesiatov commented 5 years ago

@thecb4 this should be now fixed and is verified with a test based on the code you've provided. Please let me know if this is still reproducible for you in master.

thecb4 commented 5 years ago

Works!

output now

AppPreview(displayTarget: "iOS-6.5-in", position: 1, previewImageTime: test.PreviewImageTime(format: "24/999 1000/nonDrop", value: "00:00:17:01"))