web-dev-qa-db-ja.com

SwiftでのAlamofireによるXMLデータの処理

現在のiosプロジェクトでココアポッドを使い始めました。 iosプロジェクトで簡単にコンテンツを取得するには、SOAPを使用する必要があります。Googleで検索しました。Alamofireポッドは私に最適です。Swift =プログラミング言語。

このポッドを簡単に開始しました。しかし、私のWebサービスはXMLの結果を返します。そして、このXML結果を配列するためにシリアライズしたいと思います。しかし、できません。

ブラウザでWebサービスを呼び出すと、このような結果が得られます

enter image description here

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言語?

18
Mehmet

あなたの説明を誤解しなかった場合、XMLデータを取得して解析したいと思いますか?これに関しては、応答コールバックで誤った変数を使用して処理する場合があります。 XMLドキュメントを確認するには、println(data)する必要があります。

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 を確認してください。

20
tsaiid

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 3.02015年10月および3.0.0-beta.3によるXcode 7 [〜#〜] readme [〜#〜] および Alamofire 3.0移行ガイド

私にとって正しい構文は次のとおりです。

_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)

7

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
    }
  }
}
6
irkinosor

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")
}
_

これが役に立つことを願っています。

2
gcharita

サーバーが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. 値をデータに変換する
  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
OhadM

Swift 3およびAlamofire 4:のtsaiidの答え

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.
        }
     }
0
Jason