From b5af6e33a72ac22e0252ce2057e0c24d0ed5cde6 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 2 May 2019 13:50:38 +0100 Subject: [PATCH] Fix decoding of empty sequences --- .../Decoder/XMLKeyedDecodingContainer.swift | 8 + Tests/XMLCoderTests/NamespaceTest.swift | 179 +++++++++++++++++- 2 files changed, 184 insertions(+), 3 deletions(-) diff --git a/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift b/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift index 1bd329c2..797afaf3 100644 --- a/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift +++ b/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift @@ -310,6 +310,14 @@ extension XMLKeyedDecodingContainer { decoder.codingPath.removeLast() } let box: Box + + // You can't decode sequences from attributes, but other strategies + // need special handling for empty sequences. + if strategy(key) != .attribute && elementOrNil == nil, + let empty = (type as? AnyEmptySequence.Type)?.init() as? T { + return empty + } + switch strategy(key) { case .attribute: guard diff --git a/Tests/XMLCoderTests/NamespaceTest.swift b/Tests/XMLCoderTests/NamespaceTest.swift index a02d012c..2a193786 100644 --- a/Tests/XMLCoderTests/NamespaceTest.swift +++ b/Tests/XMLCoderTests/NamespaceTest.swift @@ -9,7 +9,7 @@ import Foundation import XCTest @testable import XMLCoder -private let xmlData = """ +private let tableXML = """ Apples @@ -26,13 +26,186 @@ private struct Table: Codable, Equatable { let tr: [TR] } +private let worksheetXML = """ + + + + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + Scolumn name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + column name + + + + + + +""".data(using: .utf8)! + +private struct Cell: Codable, Equatable { + let type: String? + let s: String? + let formula: String? + let value: String? + + enum CodingKeys: String, CodingKey { + case formula = "f" + case value = "v" + case type = "t" + case s + } +} + +private struct Worksheet: Codable { + struct Data: Codable { + public let rows: [Row] + + enum CodingKeys: String, CodingKey { + case rows = "row" + } + } + + let data: Data? + + enum CodingKeys: String, CodingKey { + case data = "sheetData" + } +} + +private struct Row: Codable { + let reference: UInt + let height: Double? + let customHeight: String? + let cells: [Cell] + + enum CodingKeys: String, CodingKey { + case cells = "c" + case reference = "r" + case height = "ht" + case customHeight + } +} + class NameSpaceTest: XCTestCase { - func testDecoder() throws { + func testTable() throws { let decoder = XMLDecoder() decoder.shouldProcessNamespaces = true - let decoded = try decoder.decode(Table.self, from: xmlData) + let decoded = try decoder.decode(Table.self, from: tableXML) XCTAssertEqual(decoded, Table(tr: [.init(td: ["Apples", "Bananas"])])) } + + func testWorksheet() throws { + let decoder = XMLDecoder() + decoder.shouldProcessNamespaces = true + + let worksheet = try decoder.decode(Worksheet.self, from: worksheetXML) + XCTAssertEqual(worksheet.data?.rows[0].cells.count, 36) + } }