another.im-ios/AnotherIM/xmpp/models/XMLElement.swift
2024-12-17 16:28:30 +01:00

99 lines
2.4 KiB
Swift

import Foundation
struct XMLElement: Codable, Equatable, CustomStringConvertible {
let name: String
let xmlns: String?
let attributes: [String: String]
let content: String?
let nodes: [XMLElement]
var woClose: Bool = false
var stringRepresentation: String {
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
}
var description: String {
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" })
}
}