2016-11-29 3 views
2

Hier ist der Code, in dem ich eine SOAP-Nachricht an meinen Web Service mit meinem Integrationsschlüssel, Benutzername und Passwort gesendet habe. Ich war in der Lage, die Antwort zu erhalten und den ganzen Weg hinunter zu foundCharacters zu analysieren.Handle XML geparste Antwort in Swift

Jetzt muss ich beide Elemente innerhalb der geparsten Antwort speichern, damit ich sie später für eine andere Anfrage verwenden kann.

Ich habe nach Tutorials überall gesucht, aber ich kann nicht ruhig diese Tutorials verstehen, weil die meisten von ihnen über XML-Dateien lokal speichern und nicht von einem echten 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) 
    } 
} 

Hier ist die geparsten Antwort, die ich speichern müssen und wiederzuverwenden:

ClientCode : 8 
Permissions : 70,73,77,75,71,72 

Antwort

2

Ich sehe, dass Sie die Anmeldeinformationen in Ihrer App gespeichert werden sollen. Es ist nicht erforderlich, eine solche Datei in XML zu speichern, indem Sie die Datei schreiben. Sie können Keychain verwenden, um solche sensiblen Daten zu speichern, und Sie können jederzeit von Keychain weitere HTTP-Anfragen erhalten. Es ist sicher und sicher. Hier

ist die Schlüsselbund-Bibliothek, die ich verwenden

https://github.com/marketplacer/keychain-swift

Und eine anderer Vorschlag, den Sie nicht brauchen, ist XML zu analysieren, so schwierig wie das, versuchen diese verwenden.

https://github.com/drmohundro/SWXMLHash

Ihre SOAP Web Service-Code scheint veraltet. Es ist ein seltener Web-Service, den wir die meiste Zeit des Tages nicht benutzen und seltene Dokumentationen. Jetzt wenden sich die Leute an REST. Und Sie verwenden NSURLConnection, die in iOS 8 veraltet war. Beginnen wir also mit URLSession. Und ich werde Delegate Pattern hier verwenden. Ich habe meine Antwort sehr einfach gemacht, damit Sie es verstehen. Und Sie können alles ändern, was Sie für die Antwort benötigen.

Also, ich habe zwei Swift-Klassen. Einer ist ViewController.swift und ein anderer ist SOAPService.swift.

So behandeln wir SOAPService mit Delegate-Muster.

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

} 

Also, das ist, wie wir Gonna SOAP Web Services umgehen mit URLSession.

Also, wie erhalten wir die Antwortdaten von ViewController?

Es ist einfach. Wir implementieren nur die Protokoll Methoden hier.

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

} 

Was ist SOAP-Nachricht? Wie REST, müssen wir Parameter zu jedem spezifischen Service-Recht schicken?

eg. "www.api.com/services/verifytoken?username=Thiha&password=dwadwdada" 
(BASE_URL/SOAPAction?ParamName1=""&ParamName2="") 
[GET Request in REST Web Service] 

Um HTTP in SOAP zu beantragen, müssen Sie SOAP-Nachricht in schreiben, um die SOAP-Web-Service, damit Sie verstehen

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

Ich hoffe, es hilft . Da Sie Anfänger darin sind, schlage ich vor, die Dokumentationen über NSURLSession für weitere Konfiguration zu lesen und zu lesen, wie XML mit dem SWXMLHash, das ich erwähnte, analysiert wird. Viel Glück!

+0

Ich habe eine Frage zu den Konstanten. public let verify_token = "VerifyToken" << Ich habe ein Sicherheitstoken, um die Verbindung zu autorisieren, aber es muss innerhalb der Soap-Nachricht gesendet werden, genau wie der Benutzername und das Passwort, oder verstehe ich es falsch? –

+0

Nein, diese Variablen sind nur ein Beispiel für das Verständnis, einschließlich SOAP-Nachricht. –

+0

Bei SOAP, gibt es SOAPAction, BASE_URL und WSDL_URL richtig? Deshalb lasse ich es als constants.Let mir untersuchen Sie kurz auf Antwort –