我想使用XMLCoder library(使用Codable
协议)解码以下XML:
<?xml version="1.0" encoding="UTF-8"?>
<container>
<p>
<run>
<id>1518</id>
<text>I am answering it again.</text>
</run>
<properties>
<id>431</id>
<title>A Word About Wake Times
</title>
</properties>
<br/>
<run>
<id>1519</id>
<text>Hello!</text>
</run>
</p>
<p>
<run>
<id>1520</id>
<text>I am answering it again.</text>
</run>
</p>
</container>
但是非常重要的一点是将元素的顺序保持在p
元素内。例如,在第一个p
元素中有一个run
,然后是properties
,然后是br
,最后是另一个run
。
这不能用基本结构实现,因为它将尝试从与数组相同的类型中解码元素,并且不会保持一般顺序。我也尝试使用enum
,但存在相同的问题。
您知道实现此目标的某种方法吗?
当前无效代码:
struct Container: Decodable {
let paragraphs: [Paragraph]
enum CodingKeys: String, CodingKey {
case paragraphs = "p"
}
}
struct Run: Decodable {
let id: Int
let text: String
}
struct Properties: Decodable {
let id: Int
let title: String
}
struct Break: Decodable {
}
enum Entry: Decodable {
case run(Run)
case properties(Properties)
case br(Break)
private enum CodingKeys: String, CodingKey {
case run, properties, br
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
// Here, when trying to decode the run elements:
// DecodingError.typeMismatch: Expected to decode Dictionary<String, Any> but found SharedBox<UnkeyedBox> instead.
if let run = try container.decodeIfPresent(Run.self, forKey: .run) {
self = .run(run)
}
else if let properties = try container.decodeIfPresent(Properties.self, forKey: .properties) {
self = .properties(properties)
}
else {
self = .br(try container.decode(Break.self, forKey: .br))
}
}
}
struct Paragraph: Decodable {
let entries: [Entry]
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
entries = try container.decode([Entry].self)
}
}
do {
let result = try XMLDecoder().decode(Container.self, from: data)
for paragraph in result.paragraphs {
print("Paragraph :")
for entry in paragraph.entries {
switch entry {
case .run(let run):
print("Run : \(run)")
case .properties(let properties):
print("Properties : \(properties)")
case .br(let br):
print("Break : \(br)")
}
}
print("End paragraph")
}
}
catch {
print(error)
}
谢谢