Use NSXMLDocument to export opml file

This commit is contained in:
relikd
2019-01-22 21:34:14 +01:00
parent d239f295cf
commit 8e90ca742f
2 changed files with 49 additions and 38 deletions

View File

@@ -1 +1 @@
github "relikd/RSXML" "7fa835427e61d2745c02d8d779e0223d0ec2effa" github "relikd/RSXML" "8c3ca8bfc34a227588b41f07896a39fdff0f2e58"

View File

@@ -55,9 +55,11 @@
[sp beginSheetModalForWindow:window completionHandler:^(NSModalResponse result) { [sp beginSheetModalForWindow:window completionHandler:^(NSModalResponse result) {
if (result == NSModalResponseOK) { if (result == NSModalResponseOK) {
BOOL flattened = ([self radioGroupSelection:radioView] == 1); BOOL flattened = ([self radioGroupSelection:radioView] == 1);
NSString *exportString = [self exportFeedsHierarchical:!flattened inContext:moc]; NSArray<FeedGroup*> *list = [StoreCoordinator sortedListOfRootObjectsInContext:moc];
NSXMLDocument *doc = [self xmlDocumentForFeeds:list hierarchical:!flattened];
NSData *xml = [doc XMLDataWithOptions:NSXMLNodePreserveAttributeOrder | NSXMLNodePrettyPrint];
NSError *error; NSError *error;
[exportString writeToURL:sp.URL atomically:YES encoding:NSUTF8StringEncoding error:&error]; [xml writeToURL:sp.URL options:NSDataWritingAtomic error:&error];
if (error) { if (error) {
[NSApp presentError:error]; [NSApp presentError:error];
} }
@@ -198,50 +200,59 @@
/** /**
Initiate export of current core data state. Write opml header and all root items. Create NSXMLNode structure with application header nodes and body node containing feed items.
@param flag If @c YES keep parent-child structure intact. If @c NO ignore all parents and add @c Feed items only. @param flag If @c YES keep parent-child structure intact. If @c NO ignore all parents and add @c Feed items only.
@param moc Managed object context.
@return Save this string to file.
*/ */
+ (NSString*)exportFeedsHierarchical:(BOOL)flag inContext:(NSManagedObjectContext*)moc { + (NSXMLDocument*)xmlDocumentForFeeds:(NSArray<FeedGroup*>*)list hierarchical:(BOOL)flag {
NSDictionary *info = @{OPMLTitleKey : @"baRSS feeds", NSXMLElement *head = [NSXMLElement elementWithName:@"head"];
@"ownerName" : @"baRSS", [head addChild:[NSXMLElement elementWithName:@"title" stringValue:@"baRSS feeds"]];
@"dateCreated" : [self currentDayAsStringISO8601:YES]}; [head addChild:[NSXMLElement elementWithName:@"ownerName" stringValue:@"baRSS"]];
RSOPMLItem *doc = [RSOPMLItem itemWithAttributes:info]; [head addChild:[NSXMLElement elementWithName:@"dateCreated" stringValue:[self currentDayAsStringISO8601:YES]]];
@autoreleasepool {
NSArray<FeedGroup*> *arr = [StoreCoordinator sortedListOfRootObjectsInContext:moc]; NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
for (FeedGroup *item in arr) { for (FeedGroup *item in list) {
[self addChild:item toParent:doc hierarchical:flag]; [self appendChild:item toNode:body hierarchical:flag];
} }
}
return [doc exportOPMLAsString]; NSXMLElement *opml = [NSXMLElement elementWithName:@"opml"];
[opml addAttribute:[NSXMLNode attributeWithName:@"version" stringValue:@"1.0"]];
[opml addChild:head];
[opml addChild:body];
NSXMLDocument *xml = [NSXMLDocument documentWithRootElement:opml];
xml.version = @"1.0";
xml.characterEncoding = @"UTF-8";
return xml;
} }
/** /**
Build up @c RSOPMLItem structure recursively. Essentially, re-create same structure as in core data storage. Build up @c NSXMLNode structure recursively. Essentially, re-create same structure as in core data storage.
@param flag If @c NO don't add groups to export file but continue evaluation of child items. @param flag If @c NO don't add groups to export file but continue evaluation of child items.
*/ */
+ (void)addChild:(FeedGroup*)item toParent:(RSOPMLItem*)parent hierarchical:(BOOL)flag { + (void)appendChild:(FeedGroup*)item toNode:(NSXMLElement *)parent hierarchical:(BOOL)flag {
RSOPMLItem *child = [RSOPMLItem new]; if (flag || item.type != GROUP) {
[child setAttribute:item.name forKey:OPMLTitleKey]; // dont add group node if hierarchical == NO
if (flag || item.type == SEPARATOR || item.feed) { NSXMLElement *outline = [NSXMLElement elementWithName:@"outline"];
[parent addChild:child]; // dont add item if item is group and hierarchical == NO [parent addChild:outline];
} [outline addAttribute:[NSXMLNode attributeWithName:OPMLTitleKey stringValue:item.name]];
[outline addAttribute:[NSXMLNode attributeWithName:OPMLTextKey stringValue:item.name]];
if (item.type == SEPARATOR) { if (item.type == SEPARATOR) {
[child setAttribute:@"true" forKey:@"separator"]; // baRSS specific [outline addAttribute:[NSXMLNode attributeWithName:@"separator" stringValue:@"true"]]; // baRSS specific
} else if (item.feed) { } else if (item.feed) {
[child setAttribute:@"rss" forKey:OPMLTypeKey]; [outline addAttribute:[NSXMLNode attributeWithName:OPMLHMTLURLKey stringValue:item.feed.link]];
[child setAttribute:item.feed.link forKey:OPMLHMTLURLKey]; [outline addAttribute:[NSXMLNode attributeWithName:OPMLXMLURLKey stringValue:item.feed.meta.url]];
[child setAttribute:item.feed.meta.url forKey:OPMLXMLURLKey]; [outline addAttribute:[NSXMLNode attributeWithName:OPMLTypeKey stringValue:@"rss"]];
NSNumber *refreshNum = [NSNumber numberWithInteger:item.feed.meta.refreshInterval]; NSString *intervalStr = [NSString stringWithFormat:@"%d", item.feed.meta.refreshInterval];
[child setAttribute:refreshNum forKey:@"refreshInterval"]; // baRSS specific [outline addAttribute:[NSXMLNode attributeWithName:@"refreshInterval" stringValue:intervalStr]]; // baRSS specific
} else { // TODO: option to export unread state?
for (FeedGroup *subItem in [item sortedChildren]) {
[self addChild:subItem toParent:(flag ? child : parent) hierarchical:flag];
} }
parent = outline;
}
for (FeedGroup *subItem in [item sortedChildren]) {
[self appendChild:subItem toNode:parent hierarchical:flag];
} }
} }