Davie Brown
Davie Brown

Reputation: 717

Parse SOAP response using NSXMLParser from web service in Swift

I'm passing a SOAP message to a publicly available web service in swift. I can see that I am getting a SOAP response back and I am attempting to parse this using an NSXMLParser.

I was expecting to make use of the parser method which has the foundCharacters parameter - but this is only called once and only contains the string : "Error"

I want to be able to access the result which I believe should be contained within the CelsiusToFahrenheitResult tag

The web service I'm calling and the SOAP messages can be found here.

I can see that the response contains the following elements:

But why isn't the values held in these also being printed?

A similar question can be found here: Parsing SOAP response using NSXMLParser with Swift but this lacks a complete answer.

Full code for my view controller which calls the web service on button press:

import UIKit

class ViewController: UIViewController, UITextFieldDelegate, NSURLConnectionDelegate, NSXMLParserDelegate {
var mutableData:NSMutableData  = NSMutableData.alloc()

    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var textfield: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    // These counts are just for my own reference - checking these later.
    var didStartElement = 0
    var didEndElement = 0
    var foundCharacters = 0

  func callWebService(){

    // This would likely be taken from an input.
    var celcius = "10";


    var soapMessage = "<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><CelsiusToFahrenheit xmlns='http://www.w3schools.com/webservices/tempconvert.asmx'><Celsius>\(celcius)</Celsius></CelsiusToFahrenheit></soap:Body></soap:Envelope>"

    println(soapMessage);
    var urlString =  "http://www.w3schools.com/webservices/tempconvert.asmx?op=CelsiusToFahrenheit"
    var url = NSURL(string: urlString)
    var theRequest = NSMutableURLRequest(URL: url!)
    var msgLength = String(count(soapMessage))

    theRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
    theRequest.addValue(msgLength, forHTTPHeaderField: "Content-Length")
    theRequest.addValue("http://www.w3schools.com/webservices/CelsiusToFahrenheit", forHTTPHeaderField: "SOAPAction")
    theRequest.HTTPMethod = "POST"
    theRequest.HTTPBody = soapMessage.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)

    var connection = NSURLConnection(request: theRequest, delegate: self, startImmediately: true)
    // Do NOT call start since the above call will start the connection


    }

    @IBAction func convertButtonClicked(sender: AnyObject) {

        callWebService();
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {

        println(response);

        if let httpResponse = response as? NSHTTPURLResponse {

            // Just printing the status code here.
            println("error \(httpResponse.statusCode)")


        }

        // We got a response to set the length of the data to zero since we will be adding to this
        // if we actually got any data back.
        mutableData.length = 0;
    }

    func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
        mutableData.appendData(data)
    }

    // Parse the result right after loading
    func connectionDidFinishLoading(connection: NSURLConnection!) {
        println(mutableData)

        var xmlParser = NSXMLParser(data: mutableData)
        xmlParser.delegate = self
        xmlParser.shouldProcessNamespaces = false
        xmlParser.shouldReportNamespacePrefixes = false
        xmlParser.shouldResolveExternalEntities = false
        xmlParser.parse()
    }


    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [NSObject : AnyObject]) {
        didStartElement += 1

        // Can see elements in the soap response being printed.
        println(elementName);
    }

    func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        didEndElement += 1
    }

    func parser(parser: NSXMLParser, foundCharacters string: String?) {
        foundCharacters += 1
        // This prints "Error"
        println("found chars: \(string!)");

    }
}

Upvotes: 1

Views: 2545

Answers (1)

Vladimir Kofman
Vladimir Kofman

Reputation: 1993

The problem is not with NSXMLParser. You have a problem with your request soap message, make sure to use the correct namespace:

WAS:

<CelsiusToFahrenheit xmlns='http://www.w3schools.com/webservices/tempconvert.asmx'>

FIXED:

<CelsiusToFahrenheit xmlns="http://www.w3schools.com/webservices/"> 

Upvotes: 1

Related Questions