Question

I'm trying to build a nice little class with NSXMLParser for my needs. I'm calling the class this way: ViewController.m:

[IDAN_XML_Parser setXmlString:soapMsg];
[IDAN_XML_Parser setStringToFind:@"userID"];
[IDAN_XML_Parser setHeader:kAPP_PASSWORD andHeaderValue:kAPP_HEADER];
[IDAN_XML_Parser setSetupXml:kWEB_SERVICE_URL];
[IDAN_XML_Parser prepareParsingAndGetResponse];

NSString *answer = [IDAN_XML_Parser getResponse];
NSLog(@"Response: %@", answer);

And my class is this:

.h file:

#import <Foundation/Foundation.h>

@interface IDAN_XML_Parser : NSObject <NSXMLParserDelegate, NSURLConnectionDelegate>



+ (void)setXmlString:(NSString *)theXML;
+ (void)setStringToFind:(NSString *)stringToFind;
+ (void)setSetupXml:(NSString *)webServicesURL;
+ (void)setHeader:(NSString *)headerKey andHeaderValue:(NSString *)headerValue;
+ (BOOL)prepareParsingAndGetResponse;
- (NSInteger)startParsing;
+ (BOOL)isParsingOK;
+ (IDAN_XML_Parser *)sharedXML;
+ (NSString *)getXMLString;
+ (NSString *)getResponse;




@end

.m file

#import "IDAN_XML_Parser.h"



@implementation IDAN_XML_Parser


NSString *matchingElement;
NSString *xmlString;
NSMutableData *webData;
NSURLConnection *conn;
NSString *soapHeader_key;
NSString *soapHeader_value;
NSURL *url;
BOOL isHeader = NO;
NSInteger didGetError = 0;
BOOL elementFound;
NSMutableString *soapResults;
NSString *returnedString;
NSXMLParser *xmlParser;
NSString *exceptionReason;
NSString *resultXML;


#pragma mark - Setup Parsing

+ (IDAN_XML_Parser *)sharedXML
{
    static IDAN_XML_Parser *theParser;
    @synchronized(self) {
        if (!theParser)
            theParser = [[self alloc] init];
    }
    return theParser;
}

+ (void)setXmlString:(NSString *)theXML
{
    xmlString = theXML;
    NSLog(@"\n\nXML TO SEND: %@", xmlString);
}

+ (void)setStringToFind:(NSString *)stringToFind
{
    matchingElement = stringToFind;
}

+ (void)setHeader:(NSString *)headerKey andHeaderValue:(NSString *)headerValue
{
    isHeader = YES;
    soapHeader_key = headerKey;
    soapHeader_value = headerValue;
}

+ (void)setSetupXml:(NSString *)webServicesURL
{
    url = [NSURL URLWithString:webServicesURL];
    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
    NSString *msgLength = [NSString stringWithFormat:@"%d", [xmlString length]];
    [req addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
    [req setHTTPMethod:@"POST"];
    [req setHTTPBody: [xmlString dataUsingEncoding:NSUTF8StringEncoding]];

    if (isHeader) {
        [req setValue:soapHeader_value forHTTPHeaderField:soapHeader_key];
    }

    conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];

    if (conn)
    {
        webData = [NSMutableData data];
    }
}

-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *) response
{
    [webData setLength: 0];
}

-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *) data
{
    [webData appendData:data];
}

-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *) error
{
    didGetError = 1;
    NSLog(@"\n\nConnection Error: %@", error);
}

-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
    resultXML = [[NSString alloc] initWithBytes:[webData mutableBytes]
                                                length:[webData length]
                                              encoding:NSUTF8StringEncoding];
    didGetError = 0;
    NSLog(@"\n\nRESPONSE XML: %@", resultXML);    
}

+ (BOOL)prepareParsingAndGetResponse
{
    NSInteger isParsingOK;
    isParsingOK = [[self sharedXML] startParsing];

    if (isParsingOK == 1) {
        return YES;
    } else {
        return NO;
    }
}

- (NSInteger)startParsing
{
    @try {
        xmlParser = [[NSXMLParser alloc] initWithData:webData];
        [xmlParser setDelegate:self];
        [xmlParser setShouldResolveExternalEntities:YES];
        [xmlParser parse];
    }
    @catch (NSException *exception) {
        didGetError = 1;
        exceptionReason = exception.reason;
        NSLog(@"Exception Reason: %@", exception.reason);
    }

    if (didGetError != 1) {
        didGetError = 0;
    }

    return didGetError;
}

+ (NSString *)getXMLString
{
    return resultXML;
}

+ (BOOL)isParsingOK
{
    if (didGetError == 1) { // We have error
        return 1;
    } else { // We don't have error
        return 0;
    }
}

+ (NSString *)getResponse
{
    return returnedString;
}

#pragma mark - Start Parsing

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    NSLog(@"START PARSING!");
    if ([elementName isEqualToString:matchingElement]) {
        if (!soapResults) {
            soapResults = [[NSMutableString alloc] init];
        }
        elementFound = YES;
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if (elementFound) {
        [soapResults appendString:string];
        NSLog(@"\n\nsoapResults: %@", soapResults);
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:matchingElement]) {
        returnedString = soapResults; // Save the element we found
        elementFound = NO;
    }
}

@end

I manage to send and get back the correct xml but it's actually doesn't start the parsing. Any idea how can I solve it?

Was it helpful?

Solution

You are initiating an asynchronous NSURLConnection and then immediately starting the parsing process. You need to defer the initiation of the parsing until connectionDidFinishLoading, or you should do a synchronous NSURLConnection (but obviously, not from the main queue). Thus, while you're eventually getting a response, the parsing is undoubtedly initiated before the response has been received.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top