CoreOffice / XMLCoder

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

decoder.shouldProcessNamespaces doesn't work for DynamicNodeDecoding? #208

Open Maxatma opened 3 years ago

Maxatma commented 3 years ago

Seems like

<?xml version="1.0" encoding="UTF-8"?>
<foo s:name="MY NAME IS WHO" s:id="123">456</foo>

decoder.shouldProcessNamespaces doesn't work for DynamicNodeDecoding attributes:

func testParse() {

struct Foo: Codable, DynamicNodeDecoding {
            let name, id: String
            let value: String

            enum CodingKeys: String, CodingKey {
                case name, id
                case value = ""
            }

            static func nodeDecoding(for key: CodingKey) -> XMLDecoder.NodeDecoding {
                switch key {
                case CodingKeys.name, CodingKeys.id:
                    return .attribute
                default:
                    return .element
                }
            }
        }

        guard let data = str.data(using: .utf8) else { return }
        let decoder = XMLDecoder()
        decoder.shouldProcessNamespaces = true

        let response = try! decoder.decode(Foo.self, from: data)
        print("response is ", response)
        XCTAssert(response != nil)
    }

this will produce: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "name", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "name", intValue: nil)], debugDescription: "No attribute found for key CodingKeys(stringValue: \"name\", intValue: nil) (\"name\").", underlyingError: nil))

Only workaround is doing it like that:

  func testParse() {

        struct Foo: Codable, DynamicNodeDecoding {
            let name, id: String
            let value: String

            enum CodingKeys: String, CodingKey {
                case name = "s:name"
                case id = "s:id"
                case value = ""
            }

            static func nodeDecoding(for key: CodingKey) -> XMLDecoder.NodeDecoding {
                switch key {
                case CodingKeys.name, CodingKeys.id:
                    return .attribute
                default:
                    return .element
                }
            }
        }

        guard let data = str.data(using: .utf8) else { return }
        let decoder = XMLDecoder()
        decoder.shouldProcessNamespaces = true

        let response = try! decoder.decode(Foo.self, from: data)
        print("response is ", response)
        XCTAssert(response != nil)
    }