Как работать с XML-документом с необязательными узлами, где важна последовательность узлов
Мне нужно проанализировать следующий тип XML в объект Swift:
<grandparent>
<parent_1 attr1="a">
<child_1 attr1="b"/>
<child_2 attr1="c"/>
</parent_1>
<parent_2 attr1="a">
<child_1 attr1="b"/>
<child_2 attr1="c"/>
</parent_2>
<parent_3 attr1="a">
<child_1 attr1="b"/>
<child_2 attr1="c"/>
</parent_3>
</grandparent>
Каждый из родительских узлов является необязательным, но в любом порядке, в котором они определены выше, необходимо сохранить конечный объект Swift - в этом случае это массив с родителями 1,2,3 (если они все присутствовали).
Я не ясно, как это сделать с XMLMapper. У кого-нибудь есть предложения?
2 ответа
Вам нужно определить новый тег:
<parents>
<parent id=1>...
<parent id=2>..,
</parents>
Установите атрибут id.
Вы получите элемент родителей с родительскими детьми.
Сортировать массив по идентификатору:
array.sort(by: { $0.id < $1.id })
Начиная с версии 1.5.2 XMLMapper вы можете сохранить порядок элементов, используя nodesOrder
собственностью XMLMap
, Смотрите readme здесь.
Итак, вы можете отобразить ваш XML как:
class Grandparent: XMLMappable {
var nodeName: String!
var parent_1: Parent?
var parent_2: Parent?
var parent_3: Parent?
var nodesOrder: [String]?
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
parent_1 <- map["parent_1"]
parent_2 <- map["parent_2"]
parent_3 <- map["parent_3"]
nodesOrder <- map.nodesOrder
}
}
class Parent: XMLMappable {
var nodeName: String!
var attr1: String?
var child_1Attr1: String?
var child_2Attr1: String?
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
attr1 <- map.attributes["attr1"]
child_1Attr1 <- map.attributes["child_1.attr1"]
child_2Attr1 <- map.attributes["child_2.attr1"]
}
}
Вы можете сохранить порядок, просто не делая ничего, кроме обычного отображения:
let grandparent = Grandparent(XMLString: xmlString)
Или вы можете изменить его вручную:
let grandparent = Grandparent(XMLString: xmlString)
grandparent.nodesOrder = ["parent_1", "parent_3", "parent_2"]
Если у вас много родительских элементов и вы можете изменить предоставленный XML, вам, вероятно, следует использовать массив <parent>
элементы, а не <parent_1>
, <parent_2>
а также <parent_3>
<grandparent>
<parent attr1="a">
<child_1 attr1="b"/>
<child_2 attr1="c"/>
</parent>
<parent attr1="a">
<child_1 attr1="b"/>
<child_2 attr1="c"/>
</parent>
<parent attr1="a">
<child_1 attr1="b"/>
<child_2 attr1="c"/>
</parent>
</grandparent>
В этом случае вы можете отобразить его в Array<Parent>
и вам не нужно беспокоиться о заказе:
class Grandparent: XMLMappable {
var nodeName: String!
var parents: [Parent]?
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
parents <- map["parent"]
}
}
class Parent: XMLMappable {
var nodeName: String!
var attr1: String?
var child_1Attr1: String?
var child_2Attr1: String?
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
attr1 <- map.attributes["attr1"]
child_1Attr1 <- map.attributes["child_1.attr1"]
child_2Attr1 <- map.attributes["child_2.attr1"]
}
}
Надеюсь это поможет.