Swift - 为 SOAP Web 服务创建请求和解析响应
Swift - creating requests and parsing responses for SOAP Web services
我为我创建了 2 个助手 classes。首先是一般 SOAP 请求:
import Foundation
class ApiManager : NSObject {
var token: String
class var sharedInstance: ApiManager {
struct Static {
static var instance: ApiManager?
static var disptachToken: dispatch_once_t = 0
}
dispatch_once(&Static.disptachToken) {
Static.instance = ApiManager()
}
return Static.instance!
}
override init() {
token = ""
super.init()
}
func postSOAP(message: String, urlString: String, soapAction: String, completion: (result: NSData) -> Void) {
var url = NSURL(string: urlString)
var request = NSMutableURLRequest(URL: url!)
var msgLength = String(countElements(message))
request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.addValue(msgLength, forHTTPHeaderField: "Content-Length")
request.addValue(soapAction, forHTTPHeaderField: "SOAPAction")
if (!token.isEmpty) {
request.addValue(".CAAUSGEX=" + token, forHTTPHeaderField: "Cookie")
}
request.HTTPMethod = "POST"
request.HTTPBody = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) // or false
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
completion(result: data)
})
}
}
每个请求的第二个:
class ContentManager : NSObject {
private let apiManager = ApiManager.sharedInstance
class var sharedInstance: ContentManager {
struct Static {
static var instance: ContentManager?
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token) {
Static.instance = ContentManager()
}
return Static.instance!
}
override init() {
super.init()
}
func login(email: String, password: String, completion: (token: String) -> Void) {
var soapMessage = "<?xml version='1.0' encoding='UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ns1='http://tempuri.org/'><SOAP-ENV:Body><ns1:LoginMethod><ns1:userName>" + email + "</ns1:userName><ns1:password>" + password + "</ns1:password></ns1:LoginMethod></SOAP-ENV:Body></SOAP-ENV:Envelope>"
let urlString = "https://someurl.svc/soap"
let soapAction = "http://someurl/LoginMethod"
ApiManager.sharedInstance.postSOAP(soapMessage, urlString: urlString, soapAction: soapAction) { (result) -> Void in
var error: NSError?
if let xmlDoc = AEXMLDocument(xmlData: result, error: &error) {
// prints the same XML structure as original
println(xmlDoc.xmlString)
let token = xmlDoc.root["s:Body"]["GetResponse"]["LoginTokenResult"].stringValue
println(token)
completion(token: token)
} else {
println("description: \(error?.localizedDescription)\ninfo: \(error?.userInfo)")
}
completion(token: "")
}
}
它正在运行,但我想创建更好的解决方案。首先完善requests body。是否可以从 swift class 以某种方式创建它?假设我有 class LoginMethod 和属性 userName 和 password,我会调用一些方法,它会像这样 return 字符串(值是变量):
<ns1:LoginMethod><ns1:userName>" + userName + "</ns1:userName><ns1:password>" + password + "</ns1:password></ns1:LoginMethod>
然后我会添加 xml 的开头和结尾,我会有请求。
第二个问题是解析xml。我找到了 AEXML,它工作得很好,但我又想拥有更智能的东西。我想给它 class 并尝试用 xml 中的值填充它。我的方法对于令牌来说可能足够了,但是如果我有对象的响应数组怎么办。或者如果有错误或其他参数。
感谢您的帮助。
如果您想要一个易于使用的 Soap 解析器,您应该从 WSDL 创建 soap 类。在此状态下,没有 swift 的工具,但您可以找到 objective-c 的工具。之前,我使用 WSDL2Objc 生成 objective-c 类 来提供 soap 服务(大约 70% 类 是正确的)。如果您有大型 SOAP 服务,它可以为您节省很多时间。
我刚刚在网上找到了另一个工具(但高级功能不是免费的):http://easywsdl.com/作者说它与 Swift 兼容,但我想我们必须使用 Bridging Header。通常,使用 Bridging Header,您可以在 swift 项目中导入 Objective-C 类。
虽然仍处于测试阶段,但仍然涵盖了您正在寻找的内容,并为您提供了一个可以随意修改的良好基础:
http://wsdl2swift.com
这是一个示例用法:
免责声明:我是作者。
我为我创建了 2 个助手 classes。首先是一般 SOAP 请求:
import Foundation
class ApiManager : NSObject {
var token: String
class var sharedInstance: ApiManager {
struct Static {
static var instance: ApiManager?
static var disptachToken: dispatch_once_t = 0
}
dispatch_once(&Static.disptachToken) {
Static.instance = ApiManager()
}
return Static.instance!
}
override init() {
token = ""
super.init()
}
func postSOAP(message: String, urlString: String, soapAction: String, completion: (result: NSData) -> Void) {
var url = NSURL(string: urlString)
var request = NSMutableURLRequest(URL: url!)
var msgLength = String(countElements(message))
request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.addValue(msgLength, forHTTPHeaderField: "Content-Length")
request.addValue(soapAction, forHTTPHeaderField: "SOAPAction")
if (!token.isEmpty) {
request.addValue(".CAAUSGEX=" + token, forHTTPHeaderField: "Cookie")
}
request.HTTPMethod = "POST"
request.HTTPBody = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) // or false
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
completion(result: data)
})
}
}
每个请求的第二个:
class ContentManager : NSObject {
private let apiManager = ApiManager.sharedInstance
class var sharedInstance: ContentManager {
struct Static {
static var instance: ContentManager?
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token) {
Static.instance = ContentManager()
}
return Static.instance!
}
override init() {
super.init()
}
func login(email: String, password: String, completion: (token: String) -> Void) {
var soapMessage = "<?xml version='1.0' encoding='UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ns1='http://tempuri.org/'><SOAP-ENV:Body><ns1:LoginMethod><ns1:userName>" + email + "</ns1:userName><ns1:password>" + password + "</ns1:password></ns1:LoginMethod></SOAP-ENV:Body></SOAP-ENV:Envelope>"
let urlString = "https://someurl.svc/soap"
let soapAction = "http://someurl/LoginMethod"
ApiManager.sharedInstance.postSOAP(soapMessage, urlString: urlString, soapAction: soapAction) { (result) -> Void in
var error: NSError?
if let xmlDoc = AEXMLDocument(xmlData: result, error: &error) {
// prints the same XML structure as original
println(xmlDoc.xmlString)
let token = xmlDoc.root["s:Body"]["GetResponse"]["LoginTokenResult"].stringValue
println(token)
completion(token: token)
} else {
println("description: \(error?.localizedDescription)\ninfo: \(error?.userInfo)")
}
completion(token: "")
}
}
它正在运行,但我想创建更好的解决方案。首先完善requests body。是否可以从 swift class 以某种方式创建它?假设我有 class LoginMethod 和属性 userName 和 password,我会调用一些方法,它会像这样 return 字符串(值是变量):
<ns1:LoginMethod><ns1:userName>" + userName + "</ns1:userName><ns1:password>" + password + "</ns1:password></ns1:LoginMethod>
然后我会添加 xml 的开头和结尾,我会有请求。
第二个问题是解析xml。我找到了 AEXML,它工作得很好,但我又想拥有更智能的东西。我想给它 class 并尝试用 xml 中的值填充它。我的方法对于令牌来说可能足够了,但是如果我有对象的响应数组怎么办。或者如果有错误或其他参数。
感谢您的帮助。
如果您想要一个易于使用的 Soap 解析器,您应该从 WSDL 创建 soap 类。在此状态下,没有 swift 的工具,但您可以找到 objective-c 的工具。之前,我使用 WSDL2Objc 生成 objective-c 类 来提供 soap 服务(大约 70% 类 是正确的)。如果您有大型 SOAP 服务,它可以为您节省很多时间。
我刚刚在网上找到了另一个工具(但高级功能不是免费的):http://easywsdl.com/作者说它与 Swift 兼容,但我想我们必须使用 Bridging Header。通常,使用 Bridging Header,您可以在 swift 项目中导入 Objective-C 类。
虽然仍处于测试阶段,但仍然涵盖了您正在寻找的内容,并为您提供了一个可以随意修改的良好基础:
http://wsdl2swift.com
这是一个示例用法:
免责声明:我是作者。