在swift中处理XMLparsing的响应
以下是我使用集成密钥,用户名和密码将SOAP消息发送到Web服务的代码。 我能够得到响应并将其parsing为foundCharacters。
现在我需要存储在parsing的响应中find的两个元素,以便稍后可以使用它们来处理另一个请求。
我一直在寻找教程,但我不能安静地理解这些教程,因为其中大多数是关于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) } }
这里是我需要存储和重新使用的parsing的响应:
ClientCode : 8 Permissions : 70,73,77,75,71,72
我看到你想在你的应用程序中存储凭据。 通过写入文件,不需要将这样的文件存储在XML中。 您可以使用Keychain
来存储这样的敏感数据,并且您可以在任何时候从Keychain
接收到Keychain
以接收更多的HTTP请求。 这是安全和安全的。
这是我使用的钥匙串库
https://github.com/marketplacer/keychain-swift
另一个build议是你不需要像这样难parsingXML,试试用这个。
https://github.com/drmohundro/SWXMLHash
您的SOAP Web服务代码似乎过时了。 这是罕见的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获取响应数据呢?
这很容易。 我们只是在这里实现Protocol方法。
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]
为了在SOAP中请求HTTP,您必须编写SOAP消息才能让SOAP Web Service理解
<?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>
我希望它可以帮助你。 由于您是初学者,所以我build议阅读关于NSURLSession的文档以进一步configuration,并阅读如何使用我提到的SWXMLHash来parsingXML。 祝你好运!