0

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.

Janak Nirmal
  • 22,706
  • 18
  • 63
  • 99
Pradeep Reddy Kypa
  • 3,992
  • 7
  • 57
  • 75

2 Answers2

2

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
  }
}
MrTJ
  • 13,064
  • 4
  • 41
  • 63
1

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);
}
rishi
  • 11,779
  • 4
  • 40
  • 59
  • `didEndElement` does not have `attributeDict` parameter – MrTJ Apr 20 '12 at 08:33
  • @RIP : in my example i have 26 questions. How to store all the values particular to a question no? i mean i have different values for each question no. How do i store each and every value seperately differentiating the question no? – Pradeep Reddy Kypa Apr 20 '12 at 09:13
  • You can create a data object(Class) for question, with four string instance variables - answer, qno, tin, title. Now you can save all data in this data object. And finally you will have one array of this data object. – rishi Apr 20 '12 at 09:35
  • @RIP do u have any tutorial on how to create a data object(Class) and how to access the data from the data object? Will the data object create 26 arrays in my case for all the 26 questions? – Pradeep Reddy Kypa Apr 20 '12 at 09:37
  • Terrific..Wow..i didnt know that we have something called data object something like this. Its great. Thanks a lot @RIP I will work it out and let u know if this works. I have accepted the answer and upvoted it. Thanks again. – Pradeep Reddy Kypa Apr 20 '12 at 09:56
  • Hi @rishi: I am able to store the details into an array using a class object suggested by you. But i am not able to print the same array. Can u please guide me on how to get the details and use them in my own class? – Pradeep Reddy Kypa May 14 '12 at 14:54
  • @rishi: I am able to store the element values into a data object but not able to retrieve the data from the same object. When i print the Data Object, I am just getting the memory present in the object. Here i am using an NSArray to store the data. Can u please sugggest me on how to get the details stored? – Pradeep Reddy Kypa May 15 '12 at 10:02
  • @PradeepReddyKypa - it will always show the the memory location, what you can do, you can use a for loop on array to print the details. – rishi May 15 '12 at 10:36
  • @rishi: Can u please help me in how to extract the data from that array? – Pradeep Reddy Kypa May 15 '12 at 12:56