Fetching XML online and parsing in Objective C

-

I'm going to be using code from the Lettuce iPhone app as an example for this post. The code is available on GitHub and I previously made a walkthrough on recreating it.

My XML data has no attribute nodes - thus I can make a method that's specific for this situation.

Let's say I have a few arrays that I want to populate with XML data.

@synthesize headlinesArray, linksArray, authorsArray;

And I want to initialize them and add objects in a function refresh, which I call in viewDidLoad.

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self refresh];
}

Before we work on the refresh function I want to make a static method that gets the contents of an XML node. Because my file doesn't return any attributes, this is very easy.

+(NSString *)nodeName:(NSString *)node XMLData:(NSString *)full
{
    NSString *between;
    NSRange startRange = [full rangeOfString:[NSString stringWithFormat:@"<%@>", node]];
    int start = (int)(startRange.location + startRange.length);
    int end = (int)[full rangeOfString:[NSString stringWithFormat:@"</%@>", node]].location;
    between = [full substringWithRange:NSMakeRange(start, (end-start))];
    return between;
}

First I get the location of the very end of the start tag I'm looking for. Then I get the beginning of the closing tag. substringWithRange gives me the data in between.

Here's how I would write the refresh function.

- (void) refresh{
    NSURL *URL = [NSURL URLWithString:[@"http://www.thelettuce.org/return.php" stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
    
    //  Request the url and store the response into NSData
    NSData *data = [NSData dataWithContentsOfURL:URL];
    
    NSString *response = [LettuceTableViewController nodeName:@"headlines" XMLData:[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]];
    NSMutableArray *tempHeadlines = [[NSMutableArray alloc] init];
    NSMutableArray *tempLinks = [[NSMutableArray alloc] init];
    NSMutableArray *tempAuthors = [[NSMutableArray alloc] init];
    while ([response rangeOfString:@"whole"].location != NSNotFound){
        NSString *tempWhole = [LettuceTableViewController nodeName:@"whole" XMLData:response];
        [tempHeadlines addObject:[LettuceTableViewController nodeName:@"title" XMLData:tempWhole]];
        [tempLinks addObject:[NSString stringWithFormat:@"%@",[LettuceTableViewController nodeName:@"url" XMLData:tempWhole]]];
        [tempAuthors addObject:[LettuceTableViewController nodeName:@"author" XMLData:tempWhole]];
        NSString *fullContents = [NSString stringWithFormat:@"<whole>%@</whole>", tempWhole];
        response = [response stringByReplacingOccurrencesOfString:fullContents withString:@""];
    }
    self.headlinesArray = tempHeadlines;
    self.linksArray = tempLinks;
    self.authorsArray = tempAuthors;
}

LettuceTableViewController is the name of the class which holds the XMLData function.

On line 2 I create an NSURL with the URL returning XML data. We store the response in data.

I know how the output of my XML is formatted. So I iterate through the XML data and get the info within the whole tag. After I'm done, I delete the tag from the original XML. The while loop knows we have finished when there are no more whole tags.

Finally, I sync up my actual NSArrays and my temporary ones.

Let me know how you like it. For me, it definitely beat importing an entire library just to parse some fairly simple XML.

Tags: xml parse fetch objective c ios iphone

See also: How to SSH tunnel to a Docker container on a remote server

Back to all posts

Neel Somani

About the Author

Neel Somani, a student at the University of California, Berkeley, is the founder of Apptic LLC. In addition to computer science, he's interested in philosophy and entrepreneurship. You can follow him on LinkedIn and Twitter.

comments powered by Disqus