Tuesday, 11 September 2012

How to show XML file on TableView

Parsing XML using NSXMLParser

In this post we shall have a look at the NSXMLParser class which is used to parse the xml with the help of its delegate methods.


To study in more detail about this class you can always have a close look at the documentation where everything is explained in details about this class.

Design Phase: For this post i shall parse the xml file present online i.e. I will be parsing the rss feeds of apple, here's the view at the final output that we will have once you finish reading this post.


 Step 1: Open Xcode and create a windows based application and give the project an appropriate name and after doing that add the table view controller subclass file into your project.



After adding the subclass file add one more file which will be the subclass of the NSObject class the reason why we are adding this file is because in future if it is required to parse one or more nodes from the xml file then in that case we can just create new properties and store the data in these properties which later can be assigned to a mutable array (You will understand this part as we proceed with the tutorial) also the properties that we create in this file act as a temporary storage of the node that we parse. 



Once you are finish adding the NSObject subclass declare the properties for xmlLink and xmlTitle which will be of NSString type and don't forget to synthesize them.

Here's a view at the .h file of the NSObject subclass, name of my NSObject subclass file is XMLStringFile you may give any name of your choice


#import <Foundation/Foundation.h>


@interface XMLStringFile : NSObject 
{
NSString *xmlLink,*xmlTitle;
}
@property (nonatomic,retain) NSString *xmlLink,*xmlTitle;
@end


and here's the view at the .m part of the NSObject subclass


#import "XMLStringFile.h"


@implementation XMLStringFile
@synthesize xmlLink,xmlTitle;
@end


Step 2: Now select the tableviewController subclass file and add the following code.


#import <UIKit/UIKit.h>
#import "XMLStringFile.h"
@interface MainRssTableViewController : UITableViewController <NSXMLParserDelegate>
{
//mutable array to store the data from the rss feeds and then display it inside the table using the tables delegate and datasource method.
NSMutableArray *rssOutputData_MutableArray;
//to store the data from the xml node
NSMutableString *nodecontent;
//declaring the object of NSXMLParser which will be used for parsing
NSXMLParser *xmlParserObject;
//declaring the object of the NSObject subclass file
XMLStringFile *XMLStringFileObject;
}
@end


maximum part of the code is explained via comments.

After declaring all the variables its time to allocate memory for the variables that you declared



// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    
    rssOutputData = [[NSMutableArray alloc]init];
    
    //declare the object of allocated variable
    NSData *xmlData=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:@"http://images.apple.com/main/rss/hotnews/hotnews.rss"]];
    
    //allocate memory for parser as well as 
    xmlParserObject =[[NSXMLParser alloc]initWithData:xmlData];
    [xmlParserObject setDelegate:self];
    
    //asking the xmlparser object to beggin with its parsing
    [xmlParserObject parse];
    
    //releasing the object of NSData as a part of memory management
    [xmlData release];
}


Step 3: Now its time to add the NSXMLParser delegate methods, the delegate methods that i have used for the parsing are given below with their appropriate meaning

a)- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedNameattributes:(NSDictionary *)attributeDict


The above delegate method is sent by a parser object to its delegate when it encounters a start tag for a given element.


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


The above delegate method is sent by a parser object to provide its delegate with a string representing all or part of the characters of the current element.


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


The above delegate method is sent by a parser object to its delegate when it encounters an end tag for a specific element.


To know more delegate method of the NSXMLParser have a look at this link.

Step 4: Implementing the delegate method


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
//if the element name is item then only i am assigning memory to the NSObject subclass
if ([elementName isEqualToString:@"item"]) 
{
XMLStringFileObject = [[XMLStringFile alloc]init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//what ever data i am getting from the node i am appending it to the nodecontent variable after i trim that data for white space or new line character
[nodecontent appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
//i am saving the data inside the properties of the XMLStringFileObject from the nodecontent variable
if ([elementName isEqualToString:@"title"]) 
{
XMLStringFileObject.xmlTitle = nodecontent;
}
else if ([elementName isEqualToString:@"link"]) 
{
XMLStringFileObject.xmlLink = nodecontent;
}
//finally in the end when the item tag is encountered i am adding the data inside the mutable array 
if([elementName isEqualToString:@"item"])
{
[rssOutputData_MutableArray addObject:XMLStringFileObject];
[XMLStringFileObject release];
}
//release the data from the mutable string variable
[nodecontent release];
//reallocate the memory to get the new data from the xml file
nodecontent = [[NSMutableString alloc]init];
}




Step 5: Now finally before running this application perform some memory management stuff in the dealloc method and then inside the app delegate.m file create the object of the UITableViewController subclass and then add this class view to the window





- (void)dealloc 
{
[rssOutputData_MutableArray release];
[xmlParserObject release];
        [super dealloc];
}

Now we have to set the detailLabel and textLabel of the table view and that is done inside the cellForRowAtIndexPath delegate method of table view

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }
    
    // Configure the cell...
[cell.textLabel setFont: [UIFont fontWithName:@"Verdana" size:12]];
[cell.detailTextLabel setFont:[UIFont fontWithName:@"Verdana" size:12]];
cell.textLabel.text = [[rssOutputData_MutableArray objectAtIndex:indexPath.row]xmlTitle];
cell.detailTextLabel.text = [[rssOutputData_MutableArray objectAtIndex:indexPath.row]xmlLink];
    
    return cell;
}

Now after doing this run your application and you will get the output which looks like this

 You may download the source code from here


i hope that this post has helped you out in understanding the concepts of xml parsing, if you have any queries related to xml parsing feel free to ask me via comments, mail or via facebook until then happy iCoding and have a great Day.

2 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. how to get images in table view give me example

    ReplyDelete