Skip to content

Commit

Permalink
Initial support for userInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
drmohundro committed Jan 11, 2018
1 parent 6d2b827 commit d010c0e
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 5 deletions.
24 changes: 22 additions & 2 deletions Source/SWXMLHash.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public class SWXMLHashOptions {

/// Encoding used for XML parsing. Default is set to UTF8
public var encoding = String.Encoding.utf8

/// Any contextual information set by the user for encoding
public var userInfo = [CodingUserInfoKey: Any]()
}

/// Simple XML parser
Expand Down Expand Up @@ -252,6 +255,7 @@ class LazyXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
required init(_ options: SWXMLHashOptions) {
self.options = options
self.root.caseInsensitive = options.caseInsensitive
self.root.userInfo = options.userInfo
super.init()
}

Expand Down Expand Up @@ -340,6 +344,7 @@ class FullXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
required init(_ options: SWXMLHashOptions) {
self.options = options
self.root.caseInsensitive = options.caseInsensitive
self.root.userInfo = options.userInfo
super.init()
}

Expand Down Expand Up @@ -556,6 +561,15 @@ public enum XMLIndexer {
return list
}

public var userInfo: [CodingUserInfoKey: Any] {
switch self {
case .element(let elem):
return elem.userInfo
default:
return [:]
}
}

/**
Allows for element lookup by matching attribute values.

Expand Down Expand Up @@ -775,11 +789,15 @@ public class XMLElement: XMLContent {
/// The name of the element
public let name: String

/// Whether the element is case insensitive or not
public var caseInsensitive: Bool

var userInfo = [CodingUserInfoKey: Any]()

/// All attributes
public var allAttributes = [String: XMLAttribute]()

/// Find an attribute by name
public func attribute(by name: String) -> XMLAttribute? {
if caseInsensitive {
return allAttributes.first(where: { $0.key.compare(name, true) })?.value
Expand Down Expand Up @@ -813,6 +831,7 @@ public class XMLElement: XMLContent {

/// All child elements (text or XML)
public var children = [XMLContent]()

var count: Int = 0
var index: Int

Expand All @@ -827,10 +846,11 @@ public class XMLElement: XMLContent {
- name: The name of the element to be initialized
- index: The index of the element to be initialized
*/
init(name: String, index: Int = 0, caseInsensitive: Bool) {
init(name: String, index: Int = 0, caseInsensitive: Bool, userInfo: [CodingUserInfoKey: Any] = [:]) {
self.name = name
self.caseInsensitive = caseInsensitive
self.index = index
self.userInfo = userInfo
}

/**
Expand All @@ -843,7 +863,7 @@ public class XMLElement: XMLContent {
*/

func addElement(_ name: String, withAttributes attributes: [String: String], caseInsensitive: Bool) -> XMLElement {
let element = XMLElement(name: name, index: count, caseInsensitive: caseInsensitive)
let element = XMLElement(name: name, index: count, caseInsensitive: caseInsensitive, userInfo: userInfo)
count += 1

children.append(element)
Expand Down
17 changes: 16 additions & 1 deletion Tests/SWXMLHashTests/LazyTypesConversionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,28 @@ class LazyTypesConversionTests: XCTestCase {
XCTFail("\(error)")
}
}

func testShouldBeAbleToGetUserInfoDuringDeserialization() {
parser = SWXMLHash.config { config in
let options = SampleUserInfo(apiVersion: .v1)
config.userInfo = [ SampleUserInfo.key: options ]
}.parse(xmlWithBasicTypes)

do {
let value: BasicItem = try parser!["root"]["basicItem"].value()
XCTAssertEqual(value.name, "the name of basic item (v1)")
} catch {
XCTFail("\(error)")
}
}
}

extension LazyTypesConversionTests {
static var allTests: [(String, (LazyTypesConversionTests) -> () throws -> Void)] {
return [
("testShouldConvertValueToNonOptional", testShouldConvertValueToNonOptional),
("testShouldConvertAttributeToNonOptional", testShouldConvertAttributeToNonOptional)
("testShouldConvertAttributeToNonOptional", testShouldConvertAttributeToNonOptional),
("testShouldBeAbleToGetUserInfoDuringDeserialization", testShouldBeAbleToGetUserInfoDuringDeserialization)
]
}
}
48 changes: 46 additions & 2 deletions Tests/SWXMLHashTests/TypeConversionBasicTypesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,29 @@ import XCTest
// swiftlint:disable line_length
// swiftlint:disable type_body_length

struct SampleUserInfo {
enum ApiVersion {
case v1
case v2
}

var apiVersion = ApiVersion.v2

func suffix() -> String {
if apiVersion == ApiVersion.v1 {
return " (v1)"
} else {
return ""
}
}

static let key = CodingUserInfoKey(rawValue: "test")!

init(apiVersion: ApiVersion) {
self.apiVersion = apiVersion
}
}

class TypeConversionBasicTypesTests: XCTestCase {
var parser: XMLIndexer?
let xmlWithBasicTypes = """
Expand Down Expand Up @@ -524,15 +547,35 @@ class TypeConversionBasicTypesTests: XCTestCase {
XCTFail("\(error)")
}
}

func testShouldBeAbleToGetUserInfoDuringDeserialization() {
parser = SWXMLHash.config { config in
let options = SampleUserInfo(apiVersion: .v1)
config.userInfo = [ SampleUserInfo.key: options ]
}.parse(xmlWithBasicTypes)

do {
let value: BasicItem = try parser!["root"]["basicItem"].value()
XCTAssertEqual(value.name, "the name of basic item (v1)")
} catch {
XCTFail("\(error)")
}
}
}

struct BasicItem: XMLIndexerDeserializable {
let name: String
let price: Double

static func deserialize(_ node: XMLIndexer) throws -> BasicItem {
var name: String = try node["name"].value()

if let opts = node.userInfo[SampleUserInfo.key] as? SampleUserInfo {
name += opts.suffix()
}

return try BasicItem(
name: node["name"].value(),
name: name,
price: node["price"].value()
)
}
Expand Down Expand Up @@ -618,7 +661,8 @@ extension TypeConversionBasicTypesTests {
("testAttributeItemShouldThrowWhenConvertingMissingToNonOptional", testAttributeItemShouldThrowWhenConvertingMissingToNonOptional),
("testAttributeItemShouldConvertAttributeItemToOptional", testAttributeItemShouldConvertAttributeItemToOptional),
("testAttributeItemShouldConvertEmptyToOptional", testAttributeItemShouldConvertEmptyToOptional),
("testAttributeItemShouldConvertMissingToOptional", testAttributeItemShouldConvertMissingToOptional)
("testAttributeItemShouldConvertMissingToOptional", testAttributeItemShouldConvertMissingToOptional),
("testShouldBeAbleToGetUserInfoDuringDeserialization", testShouldBeAbleToGetUserInfoDuringDeserialization)
]
}
}

0 comments on commit d010c0e

Please sign in to comment.