0
votes

I am not able to totally understand the flow of NSXMLParser and the delegate methods associated to them. Is there any way or any example where a detailed explanation is made how parsing is done using NSXMLParser. I have another XML where i need to store the relevant qno, tin, tout and answer into respective strings after parsing the XMl. PFB the XML.

<?xml version="1.0" encoding="UTF-8"?>
<ParticipantService>   
    <Response> 
        <FileName>CustomerSkillsIntro</FileName>
        <playlist>
            <question answer="t" qno="1" tin="71" title="Greet" tout="73"/>
            <question answer="t" qno="2" tin="74" title="Have Name Tag" tout="77"/>
            <question answer="t" qno="3" tin="78" title="Greet" tout="83"/>
            <question answer="t" qno="4" tin="109" title="Helping Do My Job" tout="112"/>
            <question answer="t" qno="5" tin="131" title="Greet Happily" tout="134"/>
            <question answer="t" qno="6" tin="141" title="Stay cheerful when resident is crabby" tout="144"/>
            <question answer="t" qno="7" tin="151" title="Bond with the new resident" tout="154"/>
            <question answer="t" qno="8" tin="161" title="Welcome cheerfully" tout="164"/>
            <question answer="t" qno="9" tin="169" title="Offer Help" tout="172"/>
            <question answer="t" qno="10" tin="178" title="Help with interest" tout="181"/>
            <question answer="t" qno="11" tin="183" title="Accompany" tout="186"/>
            <question answer="t" qno="12" tin="189" title="Pay attention to 2 resudents" tout="192"/>
            <question answer="t" qno="13" tin="199" title="Juggle the two accurately" tout="202"/>
            <question answer="t" qno="14" tin="207" title="Bring in other help when needed" tout="212"/>
            <question answer="t" qno="15" tin="219" title="Correct response I can ask" tout="222"/>
            <question answer="t" qno="16" tin="231" title="Be charming" tout="237"/>
            <question answer="t" qno="17" tin="247" title="Respond and delegate" tout="250"/>
            <question answer="t" qno="18" tin="261" title="Apologize" tout="263"/>
            <question answer="t" qno="19" tin="266" title="Offer activities" tout="270"/>
            <question answer="t" qno="20" tin="273" title="Be sensitive to needs" tout="276"/>
            <question answer="t" qno="21" tin="287" title="Offer anything you need" tout="290"/>
            <question answer="t" qno="22" tin="311" title="Take off shoes, honor unusual request" tout="315"/>
            <question answer="t" qno="23" tin="328" title="Always available menu explained" tout="331"/>
            <question answer="t" qno="24" tin="333" title="Willing to stay beyond shift" tout="336"/>
            <question answer="t" qno="25" tin="377" title="Explain policy" tout="380"/>
            <question answer="t" qno="26" tin="390" title="Understand resident" tout="396"/>
        </playlist>
        <path>lmsstaging.2xprime.com</path>
        <EncodedVideoURL>HTTP://lmsstaging.2xprime.com/test/vdos/Alzheimers.mp4</EncodedVideoURL>
    </Response>
    <RequestStatus> 
        <Code>1</Code>
        <Status>SUCCESS</Status> 
        <Message/>   
    </RequestStatus> 
</ParticipantService>

Can someone please explain me how to parse this XML and a detailed explanation about how NSXMLParser and the delegate methods work?? I want to store the "tin" and "tout" into an NSArray but i am not able to understand on how to parse it node by node. This would be very helpful.

2
Thanks @Jennis for Formatting the code. I was having a tough time on how to post the exact xml.Pradeep Reddy Kypa

2 Answers

2
votes

NSXMLParser is a so called event based XML parser or SAX type parser. It starts reading your XML from the beginning, and every time it finds a new element, a closing element or character data, it informs you about it. This is done through the delegate and you have to specify what do you want to do if these event happens by implementing the callback functions. When parsing your example XML it will call more or less these functions:

parser:yourParser didStartElement:@"playlist" namespaceURI:@"" qualifiedName:@"" attributes:attribDict
// attribDict empty

parser:yourParser didStartElement:@"question" namespaceURI:@"" qualifiedName:@"" attributes:attribDict
// attribDict = {@"answer" -> @"t", @"qno" -> @"2", @"tin" -> @"71", @"title" -> @"Greet", @"tout" -> @"73"}

parser:yourParser didEndElement:@"question" namespaceURI:@"" qualifiedName:@""

// ...repeating the last two calls for each question...

parser:yourParser didEndElement:@"playlist" namespaceURI:@"" qualifiedName:@""

So, you should implement didStartElement something like this:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
  if (elementName == @"question") {
    // save the elements of attributeDict in your array
  }
}
1
votes

Couple of delegate methods are present for NSXML Parser-

-(BOOL) parse:(NSData *)xmlData 

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

You can use following line of code in your case in method didStartElement-

if([elementName isEqualToString:@"question"]) {
    NSString *answer = [attributeDict valueForKey:@"answer"];
    NSString *qno = [attributeDict valueForKey:@"qno"];
    NSString *tin = [attributeDict valueForKey:@"tin"];
    NSString *title = [attributeDict valueForKey:@"title"];

   // Now You can store these in your preferable data models - data objects/array/dictionary
}

EDIT -

@interface Question : NSObject

@property (nonatomic, retain) NSString *answer;
@property (nonatomic, retain) NSString *qno;
@property (nonatomic, retain) NSString *tin;
@property (nonatomic, retain) NSString *title;

@end

@implementation Question

@synthesize answer = _answer;
@synthesize qno = _qno;
@synthesize tin = _tin;
@synthesize title = _title;

- (void) dealloc {
    self.answer = nil;
    self.qno = nil;
    self.tin = nil;
    self.title = nil;

    [super dealloc];         
}
@end

Now in your didStartElement method -

NSMutableArray *questionsArray = [NSMutableArray array];
if([elementName isEqualToString:@"question"]) {
    Question *questionObject = [[Question alloc] init];
    questionObject.answer = [attributeDict valueForKey:@"answer"];
    questionObject.answerqno = [attributeDict valueForKey:@"qno"];
    questionObject.answertin = [attributeDict valueForKey:@"tin"];
    questionObject.answertitle = [attributeDict valueForKey:@"title"];

    [questionsArray addObject:questionObject];
    [questionObject release];
}

You can create this array at class level and use where you want.

EDIT 2 - To extract the data from array-

//Suppose dataArray contains information - 
for (int i = 0; i < [dataArray count]; i++) {
    Question *obj = [dataArray objectAtIndex:i];
    NSLog(@"%@",obj.answer);
    NSLog(@"%@",obj.qno);
    NSLog(@"%@",obj.tin);
    NSLog(@"%@",obj.title);
}