Xml in Swift
Here’s the translation of the XML example from Go to Swift:
Our first program will demonstrate XML handling in Swift. Here’s the full source code:
import Foundation
// Plant will be mapped to XML. We use property wrappers and coding keys
// to control the XML structure. The `@objc` attribute allows us to specify
// the XML element name for the class.
@objc(plant)
class Plant: NSObject, XMLElementDecodable, XMLElementEncodable {
@objc let id: Int
@objc let name: String
@objc let origin: [String]
init(id: Int, name: String, origin: [String]) {
self.id = id
self.name = name
self.origin = origin
}
enum CodingKeys: String, CodingKey {
case id
case name
case origin
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id)
name = try container.decode(String.self, forKey: .name)
origin = try container.decode([String].self, forKey: .origin)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(name, forKey: .name)
try container.encode(origin, forKey: .origin)
}
override var description: String {
return "Plant id=\(id), name=\(name), origin=\(origin)"
}
}
// We'll use a third-party library called XMLCoder for XML encoding and decoding
import XMLCoder
func main() {
let coffee = Plant(id: 27, name: "Coffee", origin: ["Ethiopia", "Brazil"])
// Emit XML representing our plant
let encoder = XMLEncoder()
encoder.outputFormatting = .prettyPrinted
let xmlData = try! encoder.encode(coffee, withRootKey: "plant")
let xmlString = String(data: xmlData, encoding: .utf8)!
print(xmlString)
// To add a generic XML header to the output, prepend it explicitly
print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xmlString)
// Use XMLDecoder to parse XML data into a Plant object
let decoder = XMLDecoder()
let decodedPlant = try! decoder.decode(Plant.self, from: xmlData)
print(decodedPlant)
let tomato = Plant(id: 81, name: "Tomato", origin: ["Mexico", "California"])
// The parent>child>plant structure can be achieved using nested types
struct Nesting: Codable {
let plants: [Plant]
enum CodingKeys: String, CodingKey {
case plants = "parent"
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
var parentContainer = container.nestedContainer(keyedBy: PlantKeys.self, forKey: .plants)
try parentContainer.encode(plants, forKey: .child)
}
enum PlantKeys: String, CodingKey {
case child
}
}
let nesting = Nesting(plants: [coffee, tomato])
let nestingXmlData = try! encoder.encode(nesting, withRootKey: "nesting")
let nestingXmlString = String(data: nestingXmlData, encoding: .utf8)!
print(nestingXmlString)
}
main()
To run this program, you’ll need to install the XMLCoder library. You can do this using Swift Package Manager by adding the following to your Package.swift
file:
dependencies: [
.package(url: "https://github.com/MaxDesiatov/XMLCoder.git", from: "0.13.1")
],
targets: [
.target(
name: "YourTarget",
dependencies: ["XMLCoder"]
)
]
Then, you can run the program using:
$ swift run
This will output the XML representations of our Plant and Nesting structures.
Note that Swift doesn’t have built-in XML support like Go does, so we’re using a third-party library (XMLCoder) to handle XML encoding and decoding. The structure and functionality are similar to the Go example, but adapted to Swift’s syntax and conventions.
The Plant
class uses property wrappers and coding keys to control the XML structure, which is similar to how struct tags are used in Go. The Nesting
struct demonstrates how to create nested XML structures in Swift.
Remember to handle errors appropriately in a production environment, as the example uses force unwrapping for simplicity.