My NSXMLParser subclass parses all the data just fine (I have it calling NSLog every time it finds some text), but it doesnt save it, even though I tell it to add the data to my dictionary. When it reaches the
Code:
- (void)parserDidEndDocument:(NSXMLParser *)parser
, I've put a breakpoint and the debugger tells me the data dictionary(tvChannels in the code below) is completely empty. I get no errors or warnings in the code at all.
Here's my code:
Code:
//
// TVXMLParser.h
// TVGuide
//
// Created by Anja on 15/08/09.
// Copyright 2009 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "TVXML.h"
#define TVTagChannel @"channel"
#define TVTagChannelDisplayName @"display-name"
#define TVTagChannelIcon @"icon"
#define TVTagProgramme @"programme"
#define TVTagProgrammeTitle @"title"
#define TVTagProgrammeSubTitle @"sub-title"
#define TVTagProgrammeDescription @"desc"
#define TVTagProgrammeCategory @"category"
#define TVTagProgrammeAspect @"aspect"
#define TVTagProgrammeActor @"actor"
@class TVChannel;
@class TVProgramme;
@interface TVXMLParser : NSObject {
NSMutableData *tvguideData; //The xml file
NSMutableDictionary *tvChannels; //Array of all the tv-channels
TVChannel *currentChannel;
TVProgramme *currentProgramme;
NSString *currentData;
BOOL shouldStopParsing;
NSXMLParser *parser;
}
@property (retain, nonatomic) NSMutableData *tvguideData;
@property (retain, nonatomic) NSMutableDictionary *tvChannels;
@property (retain, nonatomic) TVChannel *currentChannel;
@property (retain, nonatomic) TVProgramme *currentProgramme;
@property (retain, nonatomic) NSString *currentData;
@property (retain, nonatomic) NSXMLParser *parser;
@property BOOL shouldStopParsing;
- (void) beginParsing;
@end
Code:
#import "TVXMLParser.h"
#import "TVChannel.h"
#import "TVProgramme.h"
@implementation TVXMLParser
@synthesize tvguideData;
@synthesize tvChannels;
@synthesize currentChannel;
@synthesize currentProgramme;
@synthesize currentData;
@synthesize shouldStopParsing;
@synthesize parser;
- (void) dealloc
{
[tvguideData release];
[tvChannels release];
[currentChannel release];
[currentProgramme release];
[currentData release];
[parser release];
[super dealloc];
}
- (void) beginParsing
{
parser = [[NSXMLParser alloc] initWithData:tvguideData];
[parser setDelegate:self];
[parser parse];
}
- (id) init
{
if (self = [super init])
{
NSString *path = [TVXML pathToTVXML];
NSMutableData *theData = [[NSMutableData alloc] initWithContentsOfFile:path];
self.tvguideData = theData;
[theData release];
}
return self;
}
#pragma mark NSXMLParser delegate methods
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
//Handles channels
if ([elementName isEqualToString:TVTagChannel])
{
currentChannel = [[TVChannel alloc] init];
currentChannel.channelID = [attributeDict objectForKey:@"id"];
}
else if ([elementName isEqualToString:TVTagChannelDisplayName])
{
}
else if ([elementName isEqualToString:TVTagChannelIcon])
{
currentChannel.iconURL = [NSURL URLWithString: [attributeDict objectForKey:@"src"] ];
}
//Handles programmes
else if ([elementName isEqualToString:TVTagProgramme])
{
currentProgramme = [[TVProgramme alloc] init];
//[currentProgramme.dateAndTimeStart setTimeFromUnformatedTime: [attributeDict objectForKey:@"start"] ];
//[currentProgramme.dateAndTimeEnd setTimeFromUnformatedTime: [attributeDict objectForKey:@"stop"] ];
[currentProgramme setDateAndTimeStartFromUnformatedTime: [attributeDict objectForKey:@"start"] ];
[currentProgramme setDateAndTimeEndFromUnformatedTime: [attributeDict objectForKey:@"stop"] ];
NSDate *tommorrow = [[NSDate alloc] initWithTimeIntervalSinceNow:86400.0];
if (tommorrow == [currentProgramme.dateAndTimeStart earlierDate:tommorrow])
shouldStopParsing = YES;
NSLog(@"%@", currentProgramme.channelID);
currentProgramme.channelID = [attributeDict objectForKey:@"channel"];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
//Handles channels
if ([elementName isEqualToString:TVTagChannelDisplayName])
{
if (currentChannel) {
currentChannel.channelName = currentData;
currentData = nil;
}
else
NSLog(@"Error: reached didEndElement with TVTagChannelDisplayName and currentChannel is not allocated");
}
else if ([elementName isEqualToString:TVTagChannel])
{
[tvChannels setObject:currentChannel forKey:currentChannel.channelID];
currentChannel = nil;
if ( shouldStopParsing == YES )
[parser abortParsing];
}
//Handles programmes
else if ([elementName isEqualToString:TVTagProgramme])
{
TVChannel *chan = [tvChannels objectForKey:currentProgramme.channelID];
[chan.tvProgrammes addObject:currentProgramme];
currentProgramme = nil;
}
else if ( [elementName isEqualToString:TVTagProgrammeTitle] )
{
currentProgramme.programmeTitle = currentData;
currentData = nil;
}
else if ( [elementName isEqualToString:TVTagProgrammeSubTitle] )
{
currentProgramme.programmeSubtitle = currentData;
currentData = nil;
}
else if ( [elementName isEqualToString:TVTagProgrammeDescription] )
{
currentProgramme.programmeDescription = currentData;
currentData = nil;
}
else if ( [elementName isEqualToString:TVTagProgrammeCategory] )
{
[currentProgramme.programmeCategories addObject:currentData];
currentData = nil;
}
else if ( [elementName isEqualToString:TVTagProgrammeAspect] )
{
currentProgramme.programmeAspectRatio = currentData;
currentData = nil;
}
else if ( [elementName isEqualToString:TVTagProgrammeActor] )
{
[currentProgramme.programmeCredits addObject:currentData];
currentData = nil;
}
}
- (void)parser:(NSXMLParser *)parser foundIgnorableWhitespace:(NSString *)whitespaceString
{
[currentData stringByAppendingString:whitespaceString];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSLog(@"%@", string);
[currentData stringByAppendingString:string];
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(@"An error occured while trying to parse the XML.");
NSLog(@"%@", [parseError localizedDescription]);
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSString *path = [TVXML pathToParsedXMLObject];
NSLog(@"%@", path);
if ( [NSKeyedArchiver archiveRootObject:tvChannels toFile:path] == NO)
NSLog(@"Archiving failed");
}
@end
Here are the header files of the TVProgramme and TVChannel classes:
Code:
#import <Foundation/Foundation.h>
#define kChannelIDKey @"ChannelID"
#define kProgrammeTitleKey @"ProgrammeTitle"
#define kProgrammeSubtitleKey @"ProgrammeSubtitle"
#define kProgrammeDescriptionKey @"ProgrammeDescription"
#define kProgrammeAspectRatioKey @"ProgrammeAspectRatio"
#define kProgrammeCategoriesKey @"ProgrammeCategories"
#define kProgrammeCreditsKey @"ProgrammeCredits"
#define kDateAndtimeStartKey @"DateAndTimeStart"
#define kDateAndtimeEndKey @"DateAndTimeEnd"
@interface TVProgramme : NSObject <NSCoding> {
NSString *channelID;
NSString *programmeTitle;
NSString *programmeSubtitle;
NSString *programmeDescription;
NSString *programmeAspectRatio;
NSMutableArray *programmeCategories;
NSMutableArray *programmeCredits;
NSDate *dateAndTimeStart;
NSDate *dateAndTimeEnd;
/* TVDateAndTime *dateAndTimeStart;
TVDateAndTime *dateAndTimeEnd;
TVDateAndTime *dateOfCreation; */
}
@property (retain, nonatomic) NSString *channelID;
@property (retain, nonatomic) NSString *programmeTitle;
@property (retain, nonatomic) NSString *programmeSubtitle;
@property (retain, nonatomic) NSString *programmeDescription;
@property (retain, nonatomic) NSString *programmeAspectRatio;
@property (retain, nonatomic) NSMutableArray *programmeCategories;
@property (retain, nonatomic) NSMutableArray *programmeCredits;
@property (retain, nonatomic) NSDate *dateAndTimeStart;
@property (retain, nonatomic) NSDate *dateAndTimeEnd;
/*@property (retain, nonatomic) TVDateAndTime *dateAndTimeStart;
@property (retain, nonatomic) TVDateAndTime *dateAndTimeEnd;
@property (retain, nonatomic) TVDateAndTime *dateOfCreation;*/
- (void) setDateAndTimeStartFromUnformatedTime:(NSString *)unformatedTime;
- (void) setDateAndTimeEndFromUnformatedTime:(NSString *)unformatedTime;
@end
Code:
#import <Foundation/Foundation.h>
#define kIconURLKey @"IconURL"
#define kChannelIDKey @"ChannelID"
#define kChannelNameKey @"ChannelName"
#define kTVProgrammesKey @"TVProgrammes"
@class TVProgramme;
@interface TVChannel : NSObject <NSCoding> {
NSURL *iconURL; //First time will be an http, after it'll reference a file path
NSString *channelID; //The channel ID (example: d3+.dr.dk)
NSString *channelName; //The channel's name (example: 3plus)
NSMutableArray *tvProgrammes; //Array which contains TVProgramme objects
}
@property (retain, nonatomic) NSURL *iconURL;
@property (retain, nonatomic) NSString *channelID;
@property (retain, nonatomic) NSString *channelName;
@property (retain, nonatomic) NSMutableArray *tvProgrammes;
- (TVProgramme *) getCurrentProgramme;
@end