Error shows document URI

This commit is contained in:
relikd
2019-07-28 22:27:35 +02:00
parent d9b6641a99
commit 0331f8ca59
16 changed files with 45 additions and 44 deletions

View File

@@ -35,7 +35,7 @@
+ (BOOL)isFeedParser { return YES; } + (BOOL)isFeedParser { return YES; }
- (BOOL)xmlParserWillStartParsing { - (BOOL)xmlParserWillStartParsing {
_parsedFeed = [[RSParsedFeed alloc] initWithURLString:self.documentURI]; _parsedFeed = [[RSParsedFeed alloc] initWithURL:self.documentURI];
return YES; return YES;
} }

View File

@@ -29,7 +29,6 @@
#import "NSDictionary+RSXML.h" #import "NSDictionary+RSXML.h"
@interface RSHTMLLinkParser() @interface RSHTMLLinkParser()
@property (nonatomic, readonly) NSURL *baseURL;
@property (nonatomic) NSMutableArray<RSHTMLMetadataAnchor*> *mutableLinksList; @property (nonatomic) NSMutableArray<RSHTMLMetadataAnchor*> *mutableLinksList;
@property (nonatomic) NSMutableString *currentText; @property (nonatomic) NSMutableString *currentText;
@end @end
@@ -41,7 +40,6 @@
+ (BOOL)isHTMLParser { return YES; } + (BOOL)isHTMLParser { return YES; }
- (BOOL)xmlParserWillStartParsing { - (BOOL)xmlParserWillStartParsing {
_baseURL = [NSURL URLWithString:self.documentURI];
_mutableLinksList = [NSMutableArray new]; _mutableLinksList = [NSMutableArray new];
return YES; return YES;
} }
@@ -69,7 +67,7 @@
[self.mutableLinksList addObject:obj]; [self.mutableLinksList addObject:obj];
// set link properties // set link properties
obj.tooltip = [attribs rsxml_objectForCaseInsensitiveKey:@"title"]; obj.tooltip = [attribs rsxml_objectForCaseInsensitiveKey:@"title"];
obj.link = [[NSURL URLWithString:href relativeToURL:self.baseURL] absoluteString]; obj.link = [[NSURL URLWithString:href relativeToURL:self.documentURI] absoluteString];
// begin storing data for link description // begin storing data for link description
[SAXParser beginStoringCharacters]; [SAXParser beginStoringCharacters];
self.currentText = [NSMutableString new]; self.currentText = [NSMutableString new];

View File

@@ -30,7 +30,6 @@
#import "NSDictionary+RSXML.h" #import "NSDictionary+RSXML.h"
@interface RSHTMLMetadataParser() @interface RSHTMLMetadataParser()
@property (nonatomic, readonly) NSURL *baseURL;
@property (nonatomic) NSString *faviconLink; @property (nonatomic) NSString *faviconLink;
@property (nonatomic) NSMutableArray<RSHTMLMetadataIconLink*> *iconLinks; @property (nonatomic) NSMutableArray<RSHTMLMetadataIconLink*> *iconLinks;
@property (nonatomic) NSMutableArray<RSHTMLMetadataFeedLink*> *feedLinks; @property (nonatomic) NSMutableArray<RSHTMLMetadataFeedLink*> *feedLinks;
@@ -43,7 +42,6 @@
+ (BOOL)isHTMLParser { return YES; } + (BOOL)isHTMLParser { return YES; }
- (BOOL)xmlParserWillStartParsing { - (BOOL)xmlParserWillStartParsing {
_baseURL = [NSURL URLWithString:self.documentURI];
_iconLinks = [NSMutableArray new]; _iconLinks = [NSMutableArray new];
_feedLinks = [NSMutableArray new]; _feedLinks = [NSMutableArray new];
return YES; return YES;
@@ -90,11 +88,11 @@
rel = [rel lowercaseString]; rel = [rel lowercaseString];
if ([rel isEqualToString:@"shortcut icon"]) { if ([rel isEqualToString:@"shortcut icon"]) {
self.faviconLink = [link absoluteURLWithBase:self.baseURL]; self.faviconLink = [link absoluteURLWithBase:self.documentURI];
} }
else if ([rel isEqualToString:@"icon"] || [rel hasPrefix:@"apple-touch-icon"]) { // also matching "apple-touch-icon-precomposed" else if ([rel isEqualToString:@"icon"] || [rel hasPrefix:@"apple-touch-icon"]) { // also matching "apple-touch-icon-precomposed"
RSHTMLMetadataIconLink *icon = [RSHTMLMetadataIconLink new]; RSHTMLMetadataIconLink *icon = [RSHTMLMetadataIconLink new];
icon.link = [link absoluteURLWithBase:self.baseURL]; icon.link = [link absoluteURLWithBase:self.documentURI];
icon.title = rel; icon.title = rel;
icon.sizes = [attribs rsxml_objectForCaseInsensitiveKey:@"sizes"]; icon.sizes = [attribs rsxml_objectForCaseInsensitiveKey:@"sizes"];
[self.iconLinks addObject:icon]; [self.iconLinks addObject:icon];
@@ -103,7 +101,7 @@
RSFeedType type = RSFeedTypeFromLinkTypeAttribute([attribs rsxml_objectForCaseInsensitiveKey:@"type"]); RSFeedType type = RSFeedTypeFromLinkTypeAttribute([attribs rsxml_objectForCaseInsensitiveKey:@"type"]);
if (type != RSFeedTypeNone) { if (type != RSFeedTypeNone) {
RSHTMLMetadataFeedLink *feedLink = [RSHTMLMetadataFeedLink new]; RSHTMLMetadataFeedLink *feedLink = [RSHTMLMetadataFeedLink new];
feedLink.link = [link absoluteURLWithBase:self.baseURL]; feedLink.link = [link absoluteURLWithBase:self.documentURI];
feedLink.title = [attribs rsxml_objectForCaseInsensitiveKey:@"title"]; feedLink.title = [attribs rsxml_objectForCaseInsensitiveKey:@"title"];
feedLink.type = type; feedLink.type = type;
[self.feedLinks addObject:feedLink]; [self.feedLinks addObject:feedLink];

View File

@@ -27,9 +27,9 @@
@interface RSParsedArticle : NSObject @interface RSParsedArticle : NSObject
- (nonnull instancetype)initWithFeedURL:(NSString * _Nonnull)feedURL dateParsed:(NSDate*)parsed; - (nonnull instancetype)initWithFeedURL:(NSURL * _Nonnull)feedURL dateParsed:(NSDate*)parsed;
@property (nonatomic, readonly, nonnull) NSString *feedURL; @property (nonatomic, readonly, nonnull) NSURL *feedURL;
@property (nonatomic, readonly, nonnull) NSDate *dateParsed; @property (nonatomic, readonly, nonnull) NSDate *dateParsed;
@property (nonatomic, readonly, nonnull) NSString *articleID; //Calculated. Don't get until other properties have been set. @property (nonatomic, readonly, nonnull) NSString *articleID; //Calculated. Don't get until other properties have been set.

View File

@@ -32,7 +32,7 @@
@implementation RSParsedArticle @implementation RSParsedArticle
- (instancetype)initWithFeedURL:(NSString *)feedURL dateParsed:(NSDate*)parsed { - (instancetype)initWithFeedURL:(NSURL *)feedURL dateParsed:(NSDate*)parsed {
NSParameterAssert(feedURL != nil); NSParameterAssert(feedURL != nil);
@@ -72,7 +72,7 @@
- (NSString *)calculatedUniqueID { - (NSString *)calculatedUniqueID {
NSAssert(self.feedURL != nil, @"Feed URL should always be set!"); NSAssert(self.feedURL != nil, @"Feed URL should always be set!");
NSMutableString *s = [NSMutableString stringWithString:self.feedURL]; NSMutableString *s = [NSMutableString stringWithFormat:@"%@", self.feedURL];
if (self.guid.length > 0) { if (self.guid.length > 0) {
[s appendString:self.guid]; [s appendString:self.guid];

View File

@@ -27,7 +27,7 @@
@class RSParsedArticle; @class RSParsedArticle;
@interface RSParsedFeed : NSObject @interface RSParsedFeed : NSObject
@property (nonatomic, readonly, nonnull) NSString *urlString; @property (nonatomic, readonly, nonnull) NSURL *url;
@property (nonatomic, readonly, nonnull) NSDate *dateParsed; @property (nonatomic, readonly, nonnull) NSDate *dateParsed;
@property (nonatomic, readonly, nonnull) NSArray <RSParsedArticle *> *articles; @property (nonatomic, readonly, nonnull) NSArray <RSParsedArticle *> *articles;
@@ -35,7 +35,7 @@
@property (nonatomic, nullable) NSString *link; @property (nonatomic, nullable) NSString *link;
@property (nonatomic, nullable) NSString *subtitle; @property (nonatomic, nullable) NSString *subtitle;
- (nonnull instancetype)initWithURLString:(NSString * _Nonnull)urlString; - (nonnull instancetype)initWithURL:(NSURL * _Nonnull)url;
- (RSParsedArticle *)appendNewArticle; - (RSParsedArticle *)appendNewArticle;
@end @end

View File

@@ -31,11 +31,11 @@
@implementation RSParsedFeed @implementation RSParsedFeed
- (instancetype)initWithURLString:(NSString *)urlString { - (instancetype)initWithURL:(NSURL *)url {
self = [super init]; self = [super init];
if (self) { if (self) {
_urlString = urlString; _url = url;
_mutableArticles = [NSMutableArray new]; _mutableArticles = [NSMutableArray new];
_dateParsed = [NSDate date]; _dateParsed = [NSDate date];
} }
@@ -50,7 +50,7 @@
Append new @c RSParsedArticle object to @c .articles and return newly inserted instance. Append new @c RSParsedArticle object to @c .articles and return newly inserted instance.
*/ */
- (RSParsedArticle *)appendNewArticle { - (RSParsedArticle *)appendNewArticle {
RSParsedArticle *article = [[RSParsedArticle alloc] initWithFeedURL:self.urlString dateParsed:_dateParsed]; RSParsedArticle *article = [[RSParsedArticle alloc] initWithFeedURL:self.url dateParsed:_dateParsed];
[_mutableArticles addObject:article]; [_mutableArticles addObject:article];
return article; return article;
} }

View File

@@ -28,12 +28,12 @@
@class RSXMLParser; @class RSXMLParser;
@interface RSXMLData <__covariant T : RSXMLParser *> : NSObject @interface RSXMLData <__covariant T : RSXMLParser *> : NSObject
@property (nonatomic, readonly, nonnull) NSString *urlString; @property (nonatomic, readonly, nonnull) NSURL *url;
@property (nonatomic, readonly, nullable) NSData *data; @property (nonatomic, readonly, nullable) NSData *data;
@property (nonatomic, readonly, nullable) Class parserClass; @property (nonatomic, readonly, nullable) Class parserClass;
@property (nonatomic, readonly, nullable) NSError *parserError; @property (nonatomic, readonly, nullable) NSError *parserError;
- (instancetype)initWithData:(NSData * _Nonnull)data urlString:(NSString * _Nonnull)urlString; - (instancetype)initWithData:(NSData * _Nonnull)data url:(NSURL * _Nonnull)url;
- (T _Nullable)getParser; - (T _Nullable)getParser;
- (BOOL)canParseData; - (BOOL)canParseData;

View File

@@ -35,11 +35,11 @@
static const NSUInteger minNumberOfBytesToSearch = 20; static const NSUInteger minNumberOfBytesToSearch = 20;
static const NSUInteger numberOfCharactersToSearch = 4096; static const NSUInteger numberOfCharactersToSearch = 4096;
- (instancetype)initWithData:(NSData *)data urlString:(NSString *)urlString { - (instancetype)initWithData:(NSData *)data url:(NSURL *)url {
self = [super init]; self = [super init];
if (self) { if (self) {
_data = data; _data = data;
_urlString = urlString; _url = url;
_parserError = nil; _parserError = nil;
_parserClass = [self determineParserClass]; // will set error _parserClass = [self determineParserClass]; // will set error
if (!_parserClass && _parserError) if (!_parserClass && _parserError)
@@ -112,11 +112,11 @@ static const NSUInteger numberOfCharactersToSearch = 4096;
// TODO: check for things like images and movies and return nil. // TODO: check for things like images and movies and return nil.
if (!_data || _data.length < minNumberOfBytesToSearch) { if (!_data || _data.length < minNumberOfBytesToSearch) {
// TODO: check size, type, etc. // TODO: check size, type, etc.
_parserError = RSXMLMakeError(RSXMLErrorNoData); _parserError = RSXMLMakeError(RSXMLErrorNoData, _url);
return nil; return nil;
} }
if (NSNotFound == [self findCString:"<"]) { if (NSNotFound == [self findCString:"<"]) {
_parserError = RSXMLMakeError(RSXMLErrorMissingLeftCaret); _parserError = RSXMLMakeError(RSXMLErrorMissingLeftCaret, _url);
return nil; return nil;
} }
if ([self matchAll:(const char*[]){"<rss", "<channel"} count:2]) { // RSS if ([self matchAll:(const char*[]){"<rss", "<channel"} count:2]) { // RSS
@@ -136,7 +136,7 @@ static const NSUInteger numberOfCharactersToSearch = 4096;
return [RSHTMLMetadataParser class]; return [RSHTMLMetadataParser class];
} }
if ([self findCString:"<errors xmlns='http://schemas.google"] != NSNotFound) { if ([self findCString:"<errors xmlns='http://schemas.google"] != NSNotFound) {
_parserError = RSXMLMakeError(RSXMLErrorContainsXMLErrorsTag); _parserError = RSXMLMakeError(RSXMLErrorContainsXMLErrorsTag, _url);
return nil; return nil;
} }
// else: try slower NSString conversion and search case insensitive. // else: try slower NSString conversion and search case insensitive.
@@ -154,7 +154,7 @@ static const NSUInteger numberOfCharactersToSearch = 4096;
s = [[NSString alloc] initWithBytesNoCopy:(void *)_data.bytes length:_data.length encoding:NSUnicodeStringEncoding freeWhenDone:NO]; s = [[NSString alloc] initWithBytesNoCopy:(void *)_data.bytes length:_data.length encoding:NSUnicodeStringEncoding freeWhenDone:NO];
} }
if (!s) { if (!s) {
_parserError = RSXMLMakeError(RSXMLErrorNoSuitableParser); _parserError = RSXMLMakeError(RSXMLErrorNoSuitableParser, _url);
return nil; return nil;
} }
@@ -177,7 +177,7 @@ static const NSUInteger numberOfCharactersToSearch = 4096;
} }
} }
// Try RSS anyway? libxml would return a parsing error // Try RSS anyway? libxml would return a parsing error
_parserError = RSXMLMakeError(RSXMLErrorNoSuitableParser); _parserError = RSXMLMakeError(RSXMLErrorNoSuitableParser, _url);
return nil; return nil;
} }

View File

@@ -41,5 +41,5 @@ typedef NS_ERROR_ENUM(kRSXMLParserErrorDomain, RSXMLError) {
RSXMLErrorExpectingOPML = 230 RSXMLErrorExpectingOPML = 230
}; };
NSError * RSXMLMakeError(RSXMLError code); NSError * RSXMLMakeError(RSXMLError code, NSURL *uri);
NSError * RSXMLMakeErrorWrongParser(RSXMLError expected, RSXMLError other); NSError * RSXMLMakeErrorWrongParser(RSXMLError expected, RSXMLError other, NSURL *uri);

View File

@@ -56,11 +56,16 @@ NSString * getErrorMessageForRSXMLError(RSXMLError code, RSXMLError other) {
} }
} }
NSError * RSXMLMakeError(RSXMLError code) { NSError * RSXMLMakeError(RSXMLError code, NSURL *uri) {
return RSXMLMakeErrorWrongParser(code, RSXMLErrorNoData); return RSXMLMakeErrorWrongParser(code, RSXMLErrorNoData, uri);
} }
NSError * RSXMLMakeErrorWrongParser(RSXMLError expected, RSXMLError other) { NSError * RSXMLMakeErrorWrongParser(RSXMLError expected, RSXMLError other, NSURL *uri) {
NSString *documentURI = @"";
if (uri) {
documentURI = (uri.isFileURL ? [[uri filePathURL] path] : [uri absoluteString]);
}
return [NSError errorWithDomain:kRSXMLParserErrorDomain code:expected return [NSError errorWithDomain:kRSXMLParserErrorDomain code:expected
userInfo:@{NSLocalizedDescriptionKey: getErrorMessageForRSXMLError(expected, other)}]; userInfo:@{ NSLocalizedDescriptionKey: getErrorMessageForRSXMLError(expected, other),
NSLocalizedRecoverySuggestionErrorKey: documentURI }];
} }

View File

@@ -57,7 +57,7 @@
@interface RSXMLParser<__covariant T> : NSObject <RSXMLParserDelegate, RSSAXParserDelegate> @interface RSXMLParser<__covariant T> : NSObject <RSXMLParserDelegate, RSSAXParserDelegate>
@property (nonatomic, readonly, nonnull, copy) NSString *documentURI; @property (nonatomic, readonly, nonnull, copy) NSURL *documentURI;
@property (nonatomic, assign) BOOL dontStopOnLowerAsciiBytes; @property (nonatomic, assign) BOOL dontStopOnLowerAsciiBytes;
+ (instancetype)parserWithXMLData:(RSXMLData * _Nonnull)xmlData; + (instancetype)parserWithXMLData:(RSXMLData * _Nonnull)xmlData;

View File

@@ -57,12 +57,12 @@
- (instancetype)initWithXMLData:(nonnull RSXMLData *)xmlData { - (instancetype)initWithXMLData:(nonnull RSXMLData *)xmlData {
self = [super init]; self = [super init];
if (self) { if (self) {
_documentURI = [xmlData.urlString copy]; _documentURI = [xmlData.url copy];
_xmlInputError = [xmlData.parserError copy]; _xmlInputError = [xmlData.parserError copy];
[self checkIfParserMatches:xmlData.parserClass]; [self checkIfParserMatches:xmlData.parserClass];
_xmlData = xmlData.data; _xmlData = xmlData.data;
if (!_xmlData) { if (!_xmlData) {
_xmlInputError = RSXMLMakeError(RSXMLErrorNoData); _xmlInputError = RSXMLMakeError(RSXMLErrorNoData, _documentURI);
} }
_parser = [[RSSAXParser alloc] initWithDelegate:self]; _parser = [[RSSAXParser alloc] initWithDelegate:self];
} }
@@ -159,7 +159,7 @@
RSXMLError current = [self getExpectedErrorForClass:xmlParserClass]; RSXMLError current = [self getExpectedErrorForClass:xmlParserClass];
RSXMLError expected = [self getExpectedErrorForClass:[self class]]; RSXMLError expected = [self getExpectedErrorForClass:[self class]];
if (current != expected) { if (current != expected) {
_xmlInputError = RSXMLMakeErrorWrongParser(expected, current); _xmlInputError = RSXMLMakeErrorWrongParser(expected, current, _documentURI);
return NO; return NO;
} }
} }

View File

@@ -37,7 +37,7 @@
- (RSXMLData *)xmlData:(NSString *)title urlString:(NSString *)urlString { - (RSXMLData *)xmlData:(NSString *)title urlString:(NSString *)urlString {
NSString *s = [[NSBundle bundleForClass:[self class]] pathForResource:title ofType:@"html" inDirectory:@"Resources"]; NSString *s = [[NSBundle bundleForClass:[self class]] pathForResource:title ofType:@"html" inDirectory:@"Resources"];
return [[RSXMLData alloc] initWithData:[[NSData alloc] initWithContentsOfFile:s] urlString:urlString]; return [[RSXMLData alloc] initWithData:[[NSData alloc] initWithContentsOfFile:s] url:[NSURL URLWithString:urlString]];
} }
- (void)testDaringFireball { - (void)testDaringFireball {

View File

@@ -39,7 +39,7 @@
NSString *s = [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:ext inDirectory:@"Resources"]; NSString *s = [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:ext inDirectory:@"Resources"];
if (s == nil) return nil; if (s == nil) return nil;
NSData *d = [[NSData alloc] initWithContentsOfFile:s]; NSData *d = [[NSData alloc] initWithContentsOfFile:s];
return [[RSXMLData alloc] initWithData:d urlString:[NSString stringWithFormat:@"%@.%@", name, ext]]; return [[RSXMLData alloc] initWithData:d url:[NSURL fileURLWithPath:s]];
} }
- (void)testOPMLExport { - (void)testOPMLExport {
@@ -60,7 +60,7 @@
NSLog(@"%@", exportString); NSLog(@"%@", exportString);
NSData *importData = [exportString dataUsingEncoding:NSUTF8StringEncoding]; NSData *importData = [exportString dataUsingEncoding:NSUTF8StringEncoding];
RSXMLData *xmlData = [[RSXMLData alloc] initWithData:importData urlString:@"none"]; RSXMLData *xmlData = [[RSXMLData alloc] initWithData:importData url:[NSURL URLWithString:@""]];
XCTAssertEqual(xmlData.parserClass, [RSOPMLParser class]); XCTAssertEqual(xmlData.parserClass, [RSOPMLParser class]);
RSOPMLParser *parser = [RSOPMLParser parserWithXMLData:xmlData]; RSOPMLParser *parser = [RSOPMLParser parserWithXMLData:xmlData];
XCTAssertNotNil(parser); XCTAssertNotNil(parser);
@@ -91,7 +91,7 @@
XCTAssertEqualObjects(error.domain, kRSXMLParserErrorDomain); XCTAssertEqualObjects(error.domain, kRSXMLParserErrorDomain);
xmlData = [[RSXMLData alloc] initWithData:[[NSData alloc] initWithContentsOfFile:@"/System/Library/Kernels/kernel"] xmlData = [[RSXMLData alloc] initWithData:[[NSData alloc] initWithContentsOfFile:@"/System/Library/Kernels/kernel"]
urlString:@"/System/Library/Kernels/kernel"]; url:[NSURL fileURLWithPath:@"/System/Library/Kernels/kernel"]];
XCTAssertNotNil(xmlData.parserError); XCTAssertNotNil(xmlData.parserError);
XCTAssert(xmlData.parserError.code == RSXMLErrorMissingLeftCaret); XCTAssert(xmlData.parserError.code == RSXMLErrorMissingLeftCaret);
RSXMLParser *parser2 = [xmlData getParser]; RSXMLParser *parser2 = [xmlData getParser];

View File

@@ -63,7 +63,7 @@
NSString *s = [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:ext inDirectory:@"Resources"]; NSString *s = [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:ext inDirectory:@"Resources"];
if (s == nil) return nil; if (s == nil) return nil;
NSData *d = [[NSData alloc] initWithContentsOfFile:s]; NSData *d = [[NSData alloc] initWithContentsOfFile:s];
return [[RSXMLData alloc] initWithData:d urlString:[NSString stringWithFormat:@"%@.%@", name, ext]]; return [[RSXMLData alloc] initWithData:d url:[NSURL fileURLWithPath:s]];
} }
- (RSFeedParser*)parserForFile:(NSString*)name extension:(NSString*)ext expect:(Class)cls { - (RSFeedParser*)parserForFile:(NSString*)name extension:(NSString*)ext expect:(Class)cls {
@@ -248,7 +248,7 @@
[wrongParser parseSync:&error]; [wrongParser parseSync:&error];
XCTAssertNotNil(error); XCTAssertNotNil(error);
XCTAssertEqual(error.code, RSXMLErrorExpectingOPML); XCTAssertEqual(error.code, RSXMLErrorExpectingOPML);
XCTAssertEqualObjects(error, RSXMLMakeErrorWrongParser(RSXMLErrorExpectingOPML, RSXMLErrorExpectingFeed)); XCTAssertEqualObjects(error, RSXMLMakeErrorWrongParser(RSXMLErrorExpectingOPML, RSXMLErrorExpectingFeed, xmlData.url));
XCTAssertEqualObjects(error.localizedDescription, @"Can't parse XML. OPML data expected, but RSS or Atom feed found."); XCTAssertEqualObjects(error.localizedDescription, @"Can't parse XML. OPML data expected, but RSS or Atom feed found.");
} }
@@ -314,7 +314,7 @@
NSError *error = nil; NSError *error = nil;
RSXMLData *xmlData = [self xmlFile:@"feed_1" extension:@"rss"]; RSXMLData *xmlData = [self xmlFile:@"feed_1" extension:@"rss"];
RSParsedFeed *parsedFeed = [[xmlData getParser] parseSync:&error]; RSParsedFeed *parsedFeed = [[xmlData getParser] parseSync:&error];
printf("\n\nparsing: %s\n%s\n", xmlData.urlString.UTF8String, parsedFeed.description.UTF8String); printf("\n\nparsing: %s\n%s\n", xmlData.url.path.UTF8String, parsedFeed.description.UTF8String);
XCTAssertNil(error); XCTAssertNil(error);
} }