在swift中处理XML解析的响应
以下是我用集成密钥,用户名和密码向我的Web服务发送SOAP消息的代码。我能够得到响应并将其解析为foundCharacters。在swift中处理XML解析的响应
现在我需要存储在解析的响应中找到的两个元素,以便稍后可以使用它们来处理另一个请求。
我一直在寻找各地的教程,但我不能安静地理解这些教程,因为它们大多数都是关于XML文件本地存储而不是来自真正的WebService。
class LoginCentralViewController: UIViewController, XMLParserDelegate, NSURLConnectionDelegate {
var chaveWS = ChaveWebService().chave()
var mutableData:NSMutableData = NSMutableData()
var currentElement:NSString = ""
@IBAction func btnAcessarACTION(_ sender: Any) {
let soapMessage = "<soapenv:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:log='LoginCentral'><soapenv:Header/><soapenv:Body><log:LoginCentral soapenv:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'><Autenticacao xsi:type='urn:Autenticacao' xmlns:urn='urn:RouterBoxMobile'><ChaveIntegracao xsi:type='xsd:string'>\(chaveWS)</ChaveIntegracao></Autenticacao><DadosLoginCentral xsi:type='urn:DadosLoginCentral' xmlns:urn='urn:RouterBoxMobile'><Usuario xsi:type='xsd:string'>wagner</Usuario><Senha xsi:type='xsd:string'>mudar123</Senha></DadosLoginCentral></log:LoginCentral></soapenv:Body></soapenv:Envelope>"
let urlString = "https://example.com?wsdl"
let url = NSURL (string: urlString)
let theRequest = NSMutableURLRequest(url: url! as URL)
let msgLength = soapMessage.characters.count
theRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
theRequest.addValue(String(msgLength), forHTTPHeaderField: "Content-Length")
theRequest.httpMethod = "POST"
theRequest.httpBody = soapMessage.data(using: String.Encoding.utf8, allowLossyConversion: false)
let connection = NSURLConnection(request: theRequest as URLRequest, delegate: self, startImmediately: true)
connection!.start()
if (connection != nil) {
var mutableData : Void = NSMutableData.initialize()
}
print("passou")
}
override func viewDidLoad() {
super.viewDidLoad()
}
func connection(_ connection: NSURLConnection!, didReceiveResponse response: URLResponse!) {
mutableData.length = 0;
print("passou aqui tbm")
}
func connection(_ connection: NSURLConnection!, didReceiveData data: NSData!) {
mutableData.append(data as Data)
}
func connectionDidFinishLoading(_ connection: NSURLConnection!) {
let response = NSString(data: mutableData as Data, encoding: String.Encoding.utf8.rawValue)
let xmlParser = XMLParser(data: mutableData as Data)
xmlParser.delegate = self
xmlParser.parse()
xmlParser.shouldResolveExternalEntities = true
//print(response)
}
//XMLParser
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
currentElement = elementName as NSString
//print(elementName)
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if currentElement == "LoginCentralResponse" {
print(currentElement, string)
}
print(currentElement, string)
}
}
这里是我需要保存和再利用解析响应:
ClientCode : 8
Permissions : 70,73,77,75,71,72
我看到你想你的应用程序中保存的凭证。通过编写文件,不需要在XML中存储这样的文件。您可以使用Keychain
来存储此类敏感数据,并且您可以随时接收来自Keychain
的更多HTTP请求。这是安全和安全的。
下面是我用
https://github.com/marketplacer/keychain-swift
而且彼此的建议是,你并不需要解析像XML这么困难,可以尝试使用这个钥匙串库。
https://github.com/drmohundro/SWXMLHash
你SOAP的Web服务代码似乎过时了。这是罕见的网络服务,我们不用它大部分时间和罕见的文件。现在,人们正在转向REST。并且您正在使用已在iOS 8中弃用的NSURLConnection
。因此,让我们开始使用URLSession
。我将在这里使用Delegate Pattern
。我已经让我的回答很简单,让你明白。你可以改变任何你想要处理的回应。
所以,我有两个Swift类。一个是ViewController.swift
,另一个是SOAPService.swift
。
以下是我们如何使用委托模式处理SOAPService。
import Foundation
import SWXMLHash
// At here you define your constants at global variables, or you can use structs
public let verify_token = "VerifyToken"
public let WSDL_URL = "https://api.example.com/services?wsdl"
public let BASE_URL = "https://api.example.com/"
public let VERIFY_TOKEN = BASE_URL + "VerifyToken"
// Creating protocol for data transfering
protocol SOAPServiceProtocol{
func didSuccessRequest(results : String, requestName : String)
func didFailRequest(err : String, requestName : String)
}
// I have extended the URLSessionDelegate and URLSessionTaskDelegate for passing TLS, so you might not needed until you handle HTTPS
class SOAPService : NSObject, URLSessionDelegate, URLSessionTaskDelegate{
// Here the initialization of delegate pattern to transfer data between classes
var delegate : SOAPServiceProtocol
init(delegate : SOAPServiceProtocol){
self.delegate=delegate
}
func post(wsdlURL : String, soapAction : String, soapMessage : String, serviceName : String, method : String){
// Here your request configurations
var request = URLRequest(url: URL(string: wsdlURL)!)
let msgLength = String(soapMessage.characters.count)
// Configure your soap message here
let data = soapMessage.data(using: String.Encoding.utf8, allowLossyConversion: false)
// Setting HTTP Header,Body and Method
request.httpMethod = method
request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.addValue(msgLength, forHTTPHeaderField: "Content-Length")
request.addValue(soapAction, forHTTPHeaderField: "SOAPAction")
request.httpBody = data
// URLSession configuration such as TIME OUT,etc
let urlconfig = URLSessionConfiguration.default
urlconfig.timeoutIntervalForRequest = 15
urlconfig.timeoutIntervalForResource = 15
// Initiating URLSession before making a request, I will use default here
var session = URLSession.shared
session = URLSession(configuration: urlconfig, delegate: nil, delegateQueue: nil)
// Start HTTP Request
let task = session.dataTask(with: request) {
data, response, error in
if error != nil {
// If error include,return fail
self.delegate.didFailRequest(err: "Request failed", requestName: serviceName)
return
}
guard let datastring = String(data: data!, encoding:String.Encoding(rawValue: String.Encoding.utf8.rawValue)) else{
return self.delegate.didFailRequest(err: "No Data", requestName: verify_token)
}
let xml = SWXMLHash.parse(datastring)
guard let xmlResult : String = xml["soap:Envelope"]["soap:Body"]["\(serviceName)Response"]["\(serviceName)Result"].element?.text else{
print("XML is NIL")
self.delegate.didFailRequest(err: "XML is NIL", requestName: verify_token)
return
}
// when parsing complete return the parse result
self.delegate.didSuccessRequest(results: xmlResult, requestName: verify_token)
}
task.resume()
}
// Start Writing Your SOAP Services and messages HERE
func doVerify(userName : String, password : String, methodName : String){
let soapMessage = String(format:"<?xml version=\"1.0\" encoding=\"UTF-8\"?><SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns1=\"https://api.example.com/\"><SOAP-ENV:Body><ns1:VerifyToken><ns1:UserName>%@</ns1:UserName><ns1:Password>%@</ns1:Password></ns1:VerifyToken></SOAP-ENV:Body></SOAP-ENV:Envelope>",userName,password)
post(wsdlURL: WSDL_URL, soapAction: VERIFY_TOKEN, soapMessage: soapMessage, serviceName: verify_token, method: "POST")
}
}
所以,这就是我们准备怎么使用URLSession处理SOAP Web服务。
那么,我们如何从ViewController获取响应数据呢?
这很容易。我们只是在这里实施协议方法。
import UIKit
class ViewController: UIViewController, SOAPServiceProtocol{
var soapService : SOAPService?
override func viewDidLoad() {
super.viewDidLoad()
// You need to initialize the SOAP Service to call SOAP Web Service.
soapService = SOAPService(delegate: self)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func doVerify(sender : AnyObject){
// Here I started HTTP Request
soapService?.doVerify(userName: "Thiha6245", password: "dsadafwa", methodName: verify_token)
}
// Here you implement the results which success
func didSuccessRequest(results : String, requestName: String) {
print("Results : \(results)")
switch requestName {
case verify_token:
// do handling xml parsing from result to model object and get data from model
break
default :
break
}
}
// Here you implement the failure
func didFailRequest(err: String, requestName: String) {
print("Error : \(err)")
switch requestName {
case verify_token:
// do error handling here // Request TIME OUT,Internet connection error or data error,etc
break
default :
break
}
}
}
什么是SOAP消息?像REST一样,我们必须将参数发送给每个 特定的服务权限?
eg. "www.api.com/services/verifytoken?username=Thiha&password=dwadwdada"
(BASE_URL/SOAPAction?ParamName1=""&ParamName2="")
[GET Request in REST Web Service]
为了请求HTTP的SOAP,你必须写SOAP消息中 为了让SOAP的Web服务,以了解
<?xml version=\"(Here your SOAP Version)\" encoding=\"UTF-8\"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns1=\"(Your API Base URL)/\">
<SOAP-ENV:Body>
<ns1:(SOAPAction)>
<ns1: ParamName1>""</ns1: ParamName1>
<ns1: ParamName2>""</ns1: ParamName2>
</ns1:(SOAPAction)>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
我希望它可以帮助你。由于您是初学者,因此我建议阅读关于NSURLSession的文档以进一步配置,并阅读如何使用我提到的SWXMLHash来解析XML。祝你好运!
我对常量有一些疑问。 public let verify_token =“VerifyToken”
不,这些变量只是一个让你理解的例子,包括SOAP消息。 –
在SOAP中,有SOAPAction,BASE_URL和WSDL_URL的权利吗?这就是为什么我让它声明为常量。让我简单回顾一下 –