首页 > 解决方案 > 如何处理带有节点顺序很重要的可选节点的 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 做到这一点。有人有什么建议吗?

标签: swiftxmlxmlmapper

解决方案


XMLMapper 1.5.2版开始,您可以使用. 请参阅此处的自述文件。nodesOrderXMLMap

因此,您可以像这样映射您的 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>

在这种情况下,您可以将其映射到 an 中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"]
    }
}

希望这可以帮助。


推荐阅读