James
James

Reputation: 3805

xcode 4.2 Loop Through XML Data Elements

I am very confused on how I am supposed to loop through XML elements for my current iPhone app project. I will show my code, then clarify my question.

Here is sample XML I am using:

<restaurant_details>
    <total_results>90</total_results>
    <restaurant>
        <name>Through the Garden</name>
        <distance_from_current_location>0.55</distance_from_current_location>
        <restaurant_id>123</restaurant_id>
        <longitude>-84.373734</longitude>
        <latitude>39.258606</latitude>
        <address>10738 Kenwood Rd  | cincinnati ,OH | 45242</address>
        <phone_number>513-791-2199</phone_number>
        <restaurant_type>General</restaurant_type>
    </restaurant>
</restaurant_details>

Getting data for my table:

- (void)get_table_data {
    NSString *day = [self dateInFormat:@"%A"];

    NSLog (@"At get_table_data");

    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.url.com"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if (theConnection) {
        NSLog (@"At connection");
        receivedData = [NSMutableData data];
    }
}

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

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

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {

}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
    //      NSString *theXML = [[NSString alloc] initWithBytes: [myWebData mutableBytes] length:[myWebData length] encoding:NSUTF8StringEncoding];
    //      NSLog(@"%@",theXML);[theXML release];   
    if(parser){
        parser = nil;
    }

    parser = [[NSXMLParser alloc] initWithData: receivedData];
    [parser setDelegate: self];
    [parser setShouldResolveExternalEntities: YES];
    [parser parse];
}

And my parser code:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict{
    NSLog (@"At parser");
    currentElement = elementName;

    if ([currentElement isEqualToString:@"restaurant_details"]) {
        if ([currentElement isEqualToString:@"total_results"]) {
            //NSLog(@"Element: %@", currentElement);
        }else if ([currentElement isEqualToString:@"restaurant"]) {
            restaurantObj = [[DOR_RestaurantClass alloc]init];
        }
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    if([currentElement isEqualToString:@"name"]) {
        restaurantObj.name=[NSString stringWithFormat:@"%@",string];
        //NSLog(@"Name to be saved in Array :- %@",string);
    }
    if([currentElement isEqualToString:@"distance_from_current_location"]) {
        restaurantObj.distance=[NSString stringWithFormat:@"%@",string];
        //NSLog(@"Name to be saved in Array :- %@",string);
    }
    if([currentElement isEqualToString:@"restaurant_id"]) {
        restaurantObj.restId=[NSString stringWithFormat:@"%@",string];
        //NSLog(@"Name to be saved in Array :- %@",string);
    }
    if([currentElement isEqualToString:@"address"]) {
        NSArray *stringArray = [string componentsSeparatedByString:@" | "];
        restaurantObj.address=[stringArray objectAtIndex:0];
        restaurantObj.address2=[stringArray objectAtIndex:1];
        restaurantObj.address3=[stringArray objectAtIndex:2];
        //NSLog(@"Name to be saved in Array :- %@",string);
    }
    if([currentElement isEqualToString:@"phone_number"]) {
        restaurantObj.phone=[NSString stringWithFormat:@"%@",string];
        //NSLog(@"Name to be saved in Array :- %@",string);
    }
    if([currentElement isEqualToString:@"description"]) {
        restaurantObj.description=[NSString stringWithFormat:@"%@",string];
        //NSLog(@"Name to be saved in Array :- %@",string);
    }
    if([currentElement isEqualToString:@"image_url"]) {
        restaurantObj.image=[NSString stringWithFormat:@"%@",string];
        //NSLog(@"Name to be saved in Array :- %@",string);
    }
    if([currentElement isEqualToString:@"restaurant_type"]) {
        //restaurantObj.Name=[NSString stringWithFormat:@"%@",string];
        //NSLog(@"Name to be saved in Array :- %@",string);
    }
    NSLog (@"At parser2");
    if(!currentElementValue)
        currentElementValue=[[NSMutableString alloc] initWithString:string];
    else
        [currentElementValue appendString:string];
    NSLog(@"the parser just found this text in a tag:%@",string);
}

-(void)parser:(NSXMLParser*)parser didEndElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qualifiedName {
    NSLog(@"Current element in End Element Category:- %@",currentElement);
    if([elementName isEqualToString:@"restaurant"]) {
        [listItems addObject:restaurantObj];
        NSLog(@"Array: %@", listItems);
    }else{
        currentElementValue=nil;
    }

}

Here's my .h for my restaurant class:

#import <Foundation/Foundation.h>

@interface DOR_RestaurantClass : NSObject

@property (nonatomic, retain) NSString *restId;
@property (nonatomic, retain) NSString *image;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *description;
@property (nonatomic, retain) NSString *distance;
@property (nonatomic, retain) NSString *address;
@property (nonatomic, retain) NSString *address2;
@property (nonatomic, retain) NSString *address3;
@property (nonatomic, retain) NSString *phone;
@property (nonatomic, retain) NSString *expires;

@end

And my .m:

#import "DOR_RestaurantClass.h"

@implementation DOR_RestaurantClass
@synthesize restId;
@synthesize image;
@synthesize name;
@synthesize description;
@synthesize distance;
@synthesize address;
@synthesize address2;
@synthesize address3;
@synthesize phone;
@synthesize expires;

@end

I am getting my data and so forth, so that's not an issue. My question is this: With multiple "restaurant" tags in my XML data, how do I sort through the XML so that I keep restaurant data together? I come from PHP, so I would have done a foreach on the restaurant tags, but I'm not sure how the NSXMLParser is supposed to keep the data seperated. I will be putting this information into an NSMutableArray in the end. I just don't know where to start, and cannot find any good examples on doing this. Any and all help is greatly appreciated.

This has been updated

My array listItems (NSMutableArray) is null when I print it to NSLog.

Upvotes: 1

Views: 2012

Answers (1)

mAc
mAc

Reputation: 2514

Firstly Create a Obj c class having .h and .m files only. and in that create some NSString Variables having properties like name, distance, longitude, latitude.. etc etc.

now, the code part :-

In didStartElement

in restaurant tag create a Object of that class which i just told u to create(initialize the Object):-

currentElement = elementName;

    if([currentElement isEqualToString:@"restaurant"]) {
        classObj = [[MyRestaurentClass alloc]init];
    }

Now In foundCharacters find the other tags like this :-

if([currentElement isEqualToString:@"name"]) {
        classObj.Name=[NSString stringWithFormat:@"%@",string];
        NSLog(@"Name to be saved in Array :- %@",string);
    }
    if ( [currentElement isEqualToString:@"longitude"])
    {
        classObj.longitude =[NSString stringWithFormat:@"%@",string];            
    }
}

Now Last part in didEneElement :-

Create a MutubaleArray in Parser Class and Add the classObj in that array in didEndElement :-

if([elementName isEqualToString:@"restaurent"]) {
        NSLog(@"Current element in End Element Category:- %@",currentElement);
        [ObjectsMutableArray addObject:classObj];

    }

And that's all. u r finished with parsing ..

UPDATE

Firstly you dont have to write like this in If loop i.e. :-

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict{
    NSLog (@"At parser");
    currentElement = elementName;

    if ([currentElement isEqualToString:@"restaurant_details"]) {
        if ([currentElement isEqualToString:@"total_results"]) {
            //NSLog(@"Element: %@", currentElement);
        }else if ([currentElement isEqualToString:@"restaurant"]) {
            restaurantObj = [[DOR_RestaurantClass alloc]init];
        }
    }
}

What i wrote in answer for didStartElement is Sufficient as didStartElement is called for Each n Every Tag.

See Once u create a class having NSStrings acc to your XML. Just create an Object of that class and Initialize it in didStartElement. in foundCharacters you will add the Required data in the classObject variables according to the If Conditions loops. Whenever the XMlParser comes in the </restaurent> Tag it will go in didEndElement method and there you just have to Put that classObject (object) in that Array like i did in didEndElement.

Ok Regarding your NSMutableArray, have you Initialized the Array in didStartDocument like this :-

  • (void)parserDidStartDocument:(NSXMLParser *)parser{ listItems = [[NSMutableArray alloc]init]; }

I have Changed a Above Code so please read again the whole answer carefully. If u still have any doubts Text me...

Upvotes: 2

Related Questions