2024-06-19 15:06:39 +00:00
|
|
|
import Foundation
|
|
|
|
|
2024-12-18 04:08:11 +00:00
|
|
|
public struct XMLElement: Codable, Equatable, CustomStringConvertible {
|
|
|
|
public let name: String
|
|
|
|
public let xmlns: String?
|
|
|
|
public let attributes: [String: String]
|
|
|
|
public let content: String?
|
|
|
|
public let nodes: [XMLElement]
|
|
|
|
public var woClose: Bool = false
|
2024-06-19 15:06:39 +00:00
|
|
|
|
2024-12-18 04:08:11 +00:00
|
|
|
public var stringRepresentation: String {
|
2024-06-19 15:06:39 +00:00
|
|
|
var result = "<\(name)"
|
|
|
|
for (key, value) in attributes {
|
|
|
|
let val = value.escaped
|
|
|
|
result += " \(key)='\(val)'"
|
|
|
|
}
|
|
|
|
if let xmlns {
|
|
|
|
result += " xmlns='\(xmlns)'"
|
|
|
|
}
|
|
|
|
if !nodes.isEmpty {
|
|
|
|
result += ">"
|
|
|
|
for child in nodes {
|
|
|
|
result += child.stringRepresentation
|
|
|
|
}
|
|
|
|
result += "</\(name)>"
|
|
|
|
} else {
|
|
|
|
if let content = content {
|
|
|
|
result += ">"
|
|
|
|
result += content
|
|
|
|
result += "</\(name)>"
|
|
|
|
} else {
|
|
|
|
result += woClose ? ">" : "/>"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2024-12-18 04:08:11 +00:00
|
|
|
public var description: String {
|
2024-06-19 15:06:39 +00:00
|
|
|
stringRepresentation.prettyStr
|
|
|
|
}
|
|
|
|
|
|
|
|
var data: Data {
|
|
|
|
Data(stringRepresentation.utf8)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// I decided to not use mutation functions and just
|
|
|
|
// make a new element during update
|
|
|
|
extension XMLElement {
|
|
|
|
func updateXmlns(_ new: String?) -> XMLElement {
|
|
|
|
XMLElement(
|
|
|
|
name: name,
|
|
|
|
xmlns: new,
|
|
|
|
attributes: attributes,
|
|
|
|
content: content,
|
|
|
|
nodes: nodes,
|
|
|
|
woClose: woClose
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func addNode(_ new: XMLElement) -> XMLElement {
|
|
|
|
var nodes = nodes
|
|
|
|
nodes.append(new)
|
|
|
|
|
|
|
|
return XMLElement(
|
|
|
|
name: name,
|
|
|
|
xmlns: xmlns,
|
|
|
|
attributes: attributes,
|
|
|
|
content: content,
|
|
|
|
nodes: nodes,
|
|
|
|
woClose: woClose
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateContent(_ new: String?) -> XMLElement {
|
|
|
|
guard let new else { return self }
|
|
|
|
|
|
|
|
var content = self.content ?? ""
|
|
|
|
content += new
|
|
|
|
|
|
|
|
return XMLElement(
|
|
|
|
name: name,
|
|
|
|
xmlns: xmlns,
|
|
|
|
attributes: attributes,
|
|
|
|
content: content,
|
|
|
|
nodes: nodes,
|
|
|
|
woClose: woClose
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
extension XMLElement {
|
|
|
|
static var randomId: String {
|
|
|
|
let letters = "abcdefghijklmnopqrstuvwxyz0123456789"
|
|
|
|
return String((0 ..< 8).map { _ in letters.randomElement() ?? "x" })
|
|
|
|
}
|
|
|
|
}
|