Как работать с XML-документом с необязательными узлами, где важна последовательность узлов - PullRequest
0 голосов
/ 12 января 2019

Мне нужно проанализировать следующий тип 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 ]

0 голосов
/ 12 января 2019

Начиная с версии 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"]
    }
}

Надеюсь, это поможет.

0 голосов
/ 12 января 2019

Вам необходимо определить новый тег:

<parents>
  <parent id=1>...
  <parent id=2>..,
</parents>

Установить атрибут id.

Вы получите элемент родителей с родительскими детьми.

Сортировка массива по идентификатору:

array.sort(by: { $0.id < $1.id })
...