You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift4中用SWXMLHash+Alamofire解析XML报错,求实体映射方案

Hey there! Let's tackle your problem step by step—first fixing that Sequence conformance error, then showing you how to map the XML entries into a struct for cleaner, more maintainable code.

1. Fixing the Type 'XMLIndexer' does not conform to protocol 'Sequence' Error

The root issue here is that in SWXMLHash 4.x, the result of xml["feed"]["entry"] is an XMLIndexer type, which doesn't directly conform to the Sequence protocol (so you can't loop over it directly with a for-in). To access the list of entry nodes, you need to use the all property of the XMLIndexer to get a traversable collection.

Here's the corrected request code:

Alamofire.request("https://itunes.apple.com/us/rss/topgrossingapplications/limit=10/xml").response { response in
    debugPrint(response)
    guard let data = response.data else { return }
    let xml = SWXMLHash.parse(data)
    // Access the `all` property to get a sequence of entry nodes
    let entryNodes = xml["feed"]["entry"].all
    for node in entryNodes {
        print(node["title"].text)
    }
}
2. Mapping XML Entries to a Struct/Class

To make your code more organized, you can map each XML entry tag to a custom struct. SWXMLHash provides the XMLIndexerDeserializable protocol to simplify this process.

Step 1: Define the Struct

First, create a struct that matches the data you want to extract from the XML. Below is an example that captures common fields from the iTunes RSS feed:

import SWXMLHash

struct AppEntry: XMLIndexerDeserializable {
    let title: String
    let appId: String
    let artistName: String
    let releaseDate: String
    let appUrl: String
    
    static func deserialize(_ node: XMLIndexer) throws -> AppEntry {
        return try AppEntry(
            title: node["title"].value(),
            appId: node["id"]["attributes"]["im:id"].value(),
            artistName: node["im:artist"].value(),
            releaseDate: node["im:releaseDate"]["attributes"]["label"].value(),
            appUrl: node["link"]["attributes"]["href"].value()
        )
    }
}

Step 2: Parse Directly to Struct Array

Now you can modify your request code to parse all entry nodes directly into an array of AppEntry instances. This uses SWXMLHash's built-in deserialization to handle the mapping automatically:

Alamofire.request("https://itunes.apple.com/us/rss/topgrossingapplications/limit=10/xml").response { response in
    debugPrint(response)
    guard let data = response.data else { return }
    let xml = SWXMLHash.parse(data)
    
    do {
        // Deserialize all entry nodes into an array of AppEntry
        let appEntries: [AppEntry] = try xml["feed"]["entry"].value()
        
        // Use the parsed data
        for app in appEntries {
            print("App: \(app.title) by \(app.artistName) | ID: \(app.appId)")
        }
    } catch {
        print("Parsing error: \(error.localizedDescription)")
    }
}

Notes for Optional Fields

If some fields in the XML might be missing, you can handle them as optional values in your struct. For example:

struct AppEntry: XMLIndexerDeserializable {
    let title: String
    let appId: String
    let artistName: String? // Optional field
    
    static func deserialize(_ node: XMLIndexer) throws -> AppEntry {
        return AppEntry(
            title: try node["title"].value(),
            appId: try node["id"]["attributes"]["im:id"].value(),
            artistName: node["im:artist"].value() // No `try` here since it's optional
        )
    }
}

内容的提问来源于stack exchange,提问作者Asif Raza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:02:10