How can I use CDATABlock?


#1

Hi!

I am working on the Challenge of this chapter.

I succeeded in dealing with the author and category elements. But, I couldn’t make it about the description element

It seems like CDATA in the XML document. So I used a method

[color=#FF00BF]-(void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock
{
NSString *someString = [[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];
[currentString appendFormat:someString];
}[/color]

However, it didn’t work. The string which had to be from the CDATA (the description element) would have not been appended .

Could you tell me how can I handle this…?

[code]#import <Foundation/Foundation.h>

@interface RSSItem : NSObject
{
NSString *titile;
NSString *link;
NSString *category;
NSString *author;
NSString *description;

NSMutableString *currentString;

id parentParserDelegate;

}

@property (nonatomic, assign) id parentParserDelegate;
@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *link;
@property (nonatomic, retain) NSString *category;
@property (nonatomic, retain) NSString *author;
@property (nonatomic, retain) NSString *description;

@end[/code]

[code]#import “RSSItem.h”

@implementation RSSItem

@synthesize title, link, parentParserDelegate, category, author, description;

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@“title”]) {
currentString = [[NSMutableString alloc] init];
[self setTitle:currentString];
}
else if ([elementName isEqualToString:@“link”]){
currentString = [[NSMutableString alloc] init];
[self setLink:currentString];
}
else if ([elementName isEqualToString:@“category”]){
currentString = [[NSMutableString alloc] init];
[self setCategory:currentString];
}
else if ([elementName isEqualToString:@“author”]) {
currentString = [[NSMutableString alloc] init];
[self setAuthor:currentString];
}
else if ([elementName isEqualToString:@“description”]) {
currentString = [[NSMutableString alloc] init];
}
}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[currentString appendFormat:string];
}

-(void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock
{
NSString *someString = [[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];
[currentString appendFormat:someString];
}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
[currentString release];
currentString = nil;
if ([elementName isEqualToString:@“item”]) {
[parser setDelegate:parentParserDelegate];
}
}

-(void)dealloc
{
[category release];
[title release];
[link release];
[super dealloc];
}

@end
[/code]

[code]#import “ListViewController.h”
#import “RSSChannel.h”
#import “RSSItem.h”
#import “WebViewController.h”

@implementation ListViewController

@synthesize webViewController;

-(id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
[self fetchEntries];
}
return self;
}

#pragma mark - url & request & connection

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[connection release];
connection = nil;
[xmlData release];
xmlData = nil;

NSString *errorString = [NSString stringWithFormat:@"Fectch failed: %@", [error localizedDescription]];
UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error" message:errorString delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[av show];
[av autorelease];

}

-(void)fetchEntries
{
[xmlData release];
xmlData = [[NSMutableData alloc] init];
NSURL *url = [NSURL URLWithString:
@"http://forums.bignerdranch.com/smartfeed.php?"
@“limit=NO_LIMIT&count_limit=20&sort_by=standard&feed_type=RSS2.0&feed_style=COMPACT”];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
myConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}

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

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
[parser setDelegate:self];
[parser parse];
[xmlData release];
xmlData = nil;
[connection release];
connection = nil;
[[self tableView] reloadData];

}

#pragma mark - NSXMLParser *parser : delegate Method

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqual:@“channel”])
{
[channel release];
channel = [[RSSChannel alloc] init];
[channel setParentParserDelegate:self];
[parser setDelegate:channel];
}
}

#pragma mark - View lifecycle

  • (void)viewDidLoad
    {
    [super viewDidLoad];
    header = [[NSMutableString alloc] initWithString:@“123”];
    }

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[channel items] count];
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return header;
}

  • (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
    {
    return 20.0;
    }

-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
return footer;
}

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 18.0;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50.0;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@“UITableViewCell”];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@“UITableViewCell”] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}

self.title = channel.title;

RSSItem *item = [[channel items] objectAtIndex:[indexPath section]];
[[cell textLabel] setText:[item title]];
NSLog(@"%@", item.description);// <- NULL
[[cell detailTextLabel] setText:[item description]];

header = [[NSMutableString alloc] initWithString:[item category]];
footer = [[NSMutableString alloc] initWithString:[item author]];

return cell;

}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[self navigationController] pushViewController:webViewController animated:YES];

RSSItem *entry = [[channel items] objectAtIndex:[indexPath row]];

NSURL *url = [NSURL URLWithString:[entry link]];

NSURLRequest *req = [NSURLRequest requestWithURL:url];

[[webViewController webView] loadRequest:req];

[[webViewController navigationItem] setTitle:[entry title]];

}

-(void)dealloc
{
[myConnection release];
[xmlData release];

[channel release];

[webViewcontroller release];

[footer release];
[header release];
[super dealloc];

}

@end[/code]


#2

Try logging the string you get back when you find a CData block.

Does it get called? Does it have the right information?