CoreOffice / XMLCoder

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

Fix Decoding of Arrays of Empty Elements #152

Closed bwetherfield closed 4 years ago

bwetherfield commented 4 years ago

Overview

Fixes #123 and extends #145 to accommodate decoding of arrays of empty strings or mixed arrays of non-empty and empty strings.

Example

We may now decode

<container>
    <empty/>
    <empty/>
    <empty/>
</container>

into the following type

struct EmptyArray: Equatable, Codable {
    enum CodingKeys: String, CodingKey { case empties = "empty" }
    let empties: [Empty]
}

where

struct Empty: Equatable, Codable { }

We can also decode a value of the following type

struct EmptyWrapper {
    let empty: Empty
}

from

<wrapper>
    <empty/>
</wrapper>

Further, following from #145 we can decode arrays of empty strings

<container>
    <string-type/>
    <string-type>My neighbors are empty<string-type>
    <string-type/>
</container>

as

struct EmptyArray: Equatable, Codable {
    enum CodingKeys: String, CodingKey { case stringType = "string-type" }
    let stringType: [String]
}

and variants.

Source Compatibility

In cases where we decode an array of type [String?], an empty element is now decoded as "" rather than nil, the justification being that String can itself take empty values. We use the convention that nil signifies the absence of an element (if 0 or 1 of the element are allowed) as in the updated BreakfastTest and in the following error-throwing test case.

bwetherfield commented 4 years ago

I can't quite figure out if

    func parser(_: XMLParser,
                didStartElement elementName: String,
                namespaceURI: String?,
                qualifiedName: String?,
                attributes attributeDict: [String: String] = [:])

and

    func parser(_: XMLParser,
                didEndElement _: String,
                namespaceURI _: String?,
                qualifiedName _: String?)

in XMLStackParser get called differently for these two cases in the XMLParser implementation. If so, then maybe we could tweak the parser delegate implementation, but I'm not too sure. AFAIK, XML implementations wouldn't tend to distinguish in this way as a rule, so would this cause compatibility issues more broadly?

MaxDesiatov commented 4 years ago

@bwetherfield thank you for polishing this and finding new edge cases! 🙏