在Swift中使用Alamofire处理XML数据

问题描述 投票:18回答:6

我开始在当前的ios项目中使用cocoapods。我需要使用SOAP以简单的方式为我的ios项目获取内容。我用Google搜索了它,Alamofire pod对我来说很棒。因为我使用的是Swift编程语言。

我很容易看到这个吊舱。但我的Web服务返回XML结果。我想序列化来排列这个XML结果。但我不能。

当我用浏览器调用我的Web服务时,我得到了这种结果

Alamofire响应方法是这样的:

Alamofire.request(.GET, "http://my-web-service-domain.com", parameters: nil)
         .response { (request, response, data, error) in
                     println(request)
                     println(response)
                     println(error)
                   }

当我运行此方法时,我在终端上看到此输出:

<NSMutableURLRequest: 0x170010a30> { URL: http://my-web-service-domain.com }
Optional(<NSHTTPURLResponse: 0x1704276c0> { URL: http://my-web-service-domain.com } { status code: 200, headers {
    "Cache-Control" = "private, max-age=0";
    "Content-Length" = 1020;
    "Content-Type" = "text/xml; charset=utf-8";
    Date = "Thu, 18 Jun 2015 10:57:07 GMT";
    Server = "Microsoft-IIS/7.5";
    "X-AspNet-Version" = "2.0.50727";
    "X-Powered-By" = "ASP.NET";
} })
nil

我想得到一个数组的结果,在浏览器上看到我的故事板。任何人都可以帮助我如何使用Alamofire框架或Swift语言序列化这些数据?

ios xml swift alamofire
6个回答
20
投票

如果我没有误解你的描述,我想你想获取XML数据并解析它,对吧?对此,您可以在响应回调中处理错误的变量。您应该println(data)检查XML文档。

要解析XML数据,可以考虑使用SWXMLHash。 Alamofire请求可能如下所示:

Alamofire.request(.GET, "http://my-web-service-domain.com", parameters: nil)
         .response { (request, response, data, error) in
            println(data) // if you want to check XML data in debug window.
            var xml = SWXMLHash.parse(data!)
            println(xml["UserDTO"]["FilmID"].element?.text) // output the FilmID element.
         }

有关XML管理的更多信息,请查看SWXMLHash


7
投票

Alamofire 4.x - Swift 3.x:

(请注意,在这个例子中我使用URLEncoding.default而不是URLEncoding.xml,因为xml参数排除了传递参数和标题的可能性,因此default更加舒适。)

let url = "https://httpbin.org/get"
let parameters: Parameters = ["foo": "bar"]
let headers: HTTPHeaders = [
    "Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
    "Accept": "application/json"
]
Alamofire.request(url, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: headers)
.responseString { response in
    print(" - API url: \(String(describing: response.request!))")   // original url request
    var statusCode = response.response?.statusCode

    switch response.result {
    case .success:
        print("status code is: \(String(describing: statusCode))")
        if let string = response.result.value {
            print("XML: \(string)")
        }
    case .failure(let error):
        statusCode = error._code // statusCode private
        print("status code is: \(String(describing: statusCode))")
        print(error)
    }
}

Alamofire 2015年10月3日和Xcode 7根据3.0.0-beta.3 READMEAlamofire 3.0 Migration Guide

对我来说,正确的语法是:

Alamofire.request(.GET, url, parameters: params, encoding: ParameterEncoding.URL).responsePropertyList { response in

            if let error = response.result.error {
                print("Error: \(error)")

                // parsing the data to an array
            } else if let array = response.result.value as? [[String: String]] {

                if array.isEmpty {
                    print("No data")

                } else { 
                    //Do whatever you want to do with the array here
                }
            }
        }

如果你想要一个好的XML解析器,请看看SWXMLHash

一个例子可能是:let xml = SWXMLHash.parse(string)


6
投票

截至2015年9月使用Alamofire 3.0当前版本和Xcode 7。

下面的实现具有不使用诸如SWXMLHash之类的附加外部库的优点

Alamofire.request(.GET, urlString, encoding: .PropertyList(.XMLFormat_v1_0, 0)).responsePropertyList { request, response, result in

//Note that result have two properties: error and value as of Alamofire 3.0, check the migration guide for more info

  if let error = result.error {
    print("Error: \(error)")

    // parsing the data to an array 
  } else if let array = result.value as? [[String: String]] {

    if array.isEmpty {
      print("No data")

    } else { 
      //Do whatever you want to do with the array here
    }
  }
}

2
投票

如果要将XML映射到swift对象,您还可以考虑使用XMLMapper。 (使用与ObjectMapper相同的技术)

通过实现XMLMappable协议创建您的模型:

class UserDTO: XMLMappable {
    var nodeName: String!

    var extensionData: String?
    var canChangeDeviceConfig: BooleanAtttribute?
    var canChangeDriverConfig: BooleanAtttribute?
    var canChangeFleetConfig: BooleanAtttribute?
    var canChangeGeofenceConfig: BooleanAtttribute?
    var canSaveHistory: BooleanAtttribute?
    var canViewReport: BooleanAtttribute?
    var canWatchHistory: BooleanAtttribute?
    var deliverDailyReportByEmail: BooleanAtttribute?
    var deliverDailyReportBySms: BooleanAtttribute?
    var email: String?
    var firm: String?
    var firmId: Int?
    var firstName: String?
    var id: Int?
    var isActive: Bool?
    var isAdmin: Bool?
    var lastName: String?
    var phone: String?
    var recivesDailyReport: BooleanAtttribute?
    var userName: String?

    required init(map: XMLMap) {

    }

    func mapping(map: XMLMap) {
        extensionData <- map["ExtensionData"]
        canChangeDeviceConfig <- map["CanChangeDeviceConfig"]
        canChangeDriverConfig <- map["CanChangeDriverConfig"]
        canChangeFleetConfig <- map["CanChangeFleetConfig"]
        canChangeGeofenceConfig <- map["CanChangeGeofenceConfig"]
        canSaveHistory <- map["CanSaveHistory"]
        canViewReport <- map["CanViewReport"]
        canWatchHistory <- map["CanWatchHistory"]
        deliverDailyReportByEmail <- map["DeliverDailyReportByEmail"]
        deliverDailyReportBySms <- map["DeliverDailyReportBySms"]
        email <- map["Email"]
        firm <- map["Firm"]
        firmId <- map["FirmId"]
        firstName <- map["FirstName"]
        id <- map["Id"]
        isActive <- (map["IsActive"], BooleanTransformeType(trueValue: "true", falseValue: "false"))
        isAdmin <- (map["IsAdmin"], BooleanTransformeType(trueValue: "true", falseValue: "false"))
        lastName <- map["LastName"]
        phone <- map["Phone"]
        recivesDailyReport <- map["RecivesDailyReport"]
        userName <- map["UserName"]
    }
}

class BooleanAtttribute: XMLMappable {
    var nodeName: String!

    var booleanValue: Bool?

    required init(map: XMLMap) {

    }

    func mapping(map: XMLMap) {
        booleanValue <- (map.attributes["xsi:nil"], BooleanTransformeType(trueValue: "true", falseValue: "false"))
    }
}

class Firm: XMLMappable {
    var nodeName: String!

    var extensionData: String?
    var firmTypeId: Int?
    var id: Int?
    var name: String?
    var parentFirmId: Int?

    required init(map: XMLMap) {

    }

    func mapping(map: XMLMap) {
        extensionData <- map["ExtensionData"]
        firmTypeId <- map["FirmTypeId"]
        id <- map["Id"]
        name <- map["Name"]
        parentFirmId <- map["ParentFirmId"]
    }
}

class BooleanTransformeType<T: Equatable>: XMLTransformType {
    typealias Object = Bool
    typealias XML = T

    private var trueValue: T
    private var falseValue: T

    init(trueValue: T, falseValue: T) {
        self.trueValue = trueValue
        self.falseValue = falseValue
    }

    func transformFromXML(_ value: Any?) -> Bool? {
        if let value = value as? T {
            return value == trueValue
        }
        return nil
    }

    func transformToXML(_ value: Bool?) -> T? {
        if value == true {
            return trueValue
        }
        return falseValue
    }
}

并使用XMLMapper类将XML字符串映射到模型对象:

let userDTO = XMLMapper<UserDTO>().map(XMLString: xmlString)

您可以使用Requests subspec和responseXMLObject(completionHandler:)函数将响应直接映射到模型对象中:

Alamofire.request("http://my-web-service-domain.com", method: .get).responseXMLObject { (response: DataResponse<UserDTO>) in
    let userDTO = response.result.value
    print(userDTO?.id ?? "nil")
}

我希望这很有用。


0
投票

我有一个非常独特的问题,即服务器返回一个将JSON作为字符串的XML。希望它会帮助某人。

基本上XML看起来像这样:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"Response":{"Status":"success","Result_Count":"1","Error_Description":"","Result":{"Login_result":{"user_id":"1","user_type":"1","user_name":"h4cked","user_locked":"False","user_locked_message":""}}}}</string>

正如您所看到的,实际的JSON是{"Response":....

该解决方案仅基于Alamofire 4.4。

你需要做的是:

  1. 使用.responsePropertyList
  2. 检查错误
  3. 将值转换为Data
  4. 序列化为JSON对象
  5. 转换为词典[String : Any]

这里是:

Alamofire.request(NetworkAPIPaths.pathForLogin(),
                      method: .get,
                      parameters: [APIParameters.userName.rawValue : "",
                                   APIParameters.password.rawValue : ""]).responsePropertyList
        { (response : DataResponse<Any>) in

    if let error = response.result.error
    {
        // Error...
    }
    else if let jsonFullString = response.result.value as? String
    {
        if let jsonStringAsData = jsonFullString.data(using: .utf8)
        {
            do
            {
                let jsonGhost = try JSONSerialization.jsonObject(with: jsonStringAsData, options: [])

                if let actualJSON = jsonGhost as? [String : Any]
                {
                   // actualJSON is ready to be parsed :)
                }
             }
             catch
             {
               print (error.localizedDescription)
             }
        }
    }

0
投票

tsaiid在Swift 3和Alamofire 4中的回答:

Alamofire.request("http://my-web-service-domain.com", parameters: nil) //Alamofire defaults to GET requests
     .response { response in
        if let data = response.data {
          println(data) // if you want to check XML data in debug window.
          var xml = SWXMLHash.parse(data)
          println(xml["UserDTO"]["FilmID"].element?.text) // output the FilmID element.
        }
     }
© www.soinside.com 2019 - 2024. All rights reserved.