我正在尝试使用NSXMLParser
使用来自多个单独RSS源的文章标题填充UITableView
:
for (NSString* feedString in [[NSUserDefaults standardUserDefaults] objectForKey:@"RSSFeeds"])
{
NSURL *url = [NSURL URLWithString:feedString];
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
element = elementName;
if ([element isEqualToString:@"item"])
{
item = [[NSMutableDictionary alloc] init];
title = [[NSMutableString alloc] init];
link = [[NSMutableString alloc] init];
}
}
如果只有一个RSS提要,这似乎运作良好但是只要有多个RSS提要,第二个提要的第一个标题将附加到第一个提要的最后一个标题,并且它们共享同一个单元格表格视图。
我认为这种方法是问题的核心,但我正在努力使其正常运作:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([element isEqualToString:@"title"])
{
[title appendString:string];
}
else if ([element isEqualToString:@"link"])
{
[link appendString:string];
}
}
我很欣赏我可能会忽略一些显而易见的东西,但任何指针都会受到赞赏。
我的didEnd
代码:
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"item"])
{
[item setObject:title forKey:@"title"];
[item setObject:link forKey:@"link"];
[feeds addObject:[item copy]];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
[self.tableView reloadData];
}
答案 0 :(得分:2)
使用NSXMLParser
时,完全取决于您创建对象结构,因为NSXMLParser
是愚蠢的(,我并不是说它是无功能的,我的意思是它离开了所有聪明的东西都由你决定)
NSXMLParser
只是逐行读取文件,并告诉您它在当前解析的行上找到了什么(在-foundCharacters
方法中)。
它没有告诉您前一行或即将到来的行。
我将为您提供最基本的代码,这些代码将根据解析的XML结构创建对象层次结构。
根据您当前的需求,您可以更轻松或更具辨识度。
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
//NSLog(@"started element %@", elementName);
if(resultString) {
if(eliminateWhiteSpace)
[[objects objectAtIndex:[objects count] - 1] setStringValue:[resultString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
else
[[objects objectAtIndex:[objects count] - 1] setStringValue:resultString];
resultString = nil;
}
XMLNode* currentObject = [[XMLNode alloc] init];
if(!objects) {
objects = [[NSMutableArray alloc] init];
}
[objects addObject:currentObject];
[currentObject setNodeName:elementName];
if([[attributeDict allKeys] count] > 0) {
currentObject.attributes = attributeDict;
}
}
- (void)parser:(NSXMLParser*)parser foundCharacters:(NSString *)string
{
NSLog(@"found characters %@", string);
if(!resultString) {
resultString = [[NSMutableString alloc] init];
}
[resultString appendString:string];
}
- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock
{
resultString = [[NSMutableString alloc] initWithData:CDATABlock
encoding:NSUTF8StringEncoding];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
//NSLog(@"ended element %@", elementName);
if(resultString) {
if(eliminateWhiteSpace)
[[objects objectAtIndex:[objects count] - 1] setStringValue:[resultString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
else
[[objects objectAtIndex:[objects count] - 1] setStringValue:resultString];
}
if([objects count] > 1) {
[[objects objectAtIndex:[objects count] - 2] addSubNode:[objects objectAtIndex:[objects count] - 1]];
[objects removeObjectAtIndex:[objects count] - 1];
}
resultString = nil;
}
我在那里有一些类变量和一个XMLNode
类
你必须根据自己的需要定制那些,所以我不会准确解释它们是什么
根据您的情况,您可以完全删除它们。
阅读该代码几次,您应该能够了解NSXMLParser
为您做的事情及其对您的期望。
答案 1 :(得分:1)
您好像没有重置title
或link
试试这个(不确定,因为你的逻辑有点不同寻常)
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"item"]) {
[feeds addObject:[item copy]];
}
if ([elementName isEqualToString:@"title"]) {
[item setObject:[title copy] forKey:@"title"];
title = @"";
}
if ([elementName isEqualToString:@"link"]) {
[item setObject:[link copy] forKey:@"link"];
link = @"";
}
}
答案 2 :(得分:1)
注意:不是最优化的解决方案,但应该可以使用(我稍后会对此进行编辑)
for (NSString* feedString in [[NSUserDefaults standardUserDefaults] objectForKey:@"RSSFeeds"])
{
NSURL *url = [NSURL URLWithString:feedString];
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
//declare "NSMutableString *strCurrent;" in the .h of this class
strCurrent = [NSMutableString alloc] init];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[strCurrent appendString:string];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"item"]) {
item = [[NSMutableDictionary alloc] init];
}
if ([elementName isEqualToString:@"title"]) {
strCurrent = [[NSMutableString alloc] init];
}
if ([elementName isEqualToString:@"link"]) {
strCurrent = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"title"]) {
[item setObject:strCurrent forKey:@"title"];
}
if ([elementName isEqualToString:@"link"]) {
[item setObject:strCurrent forKey:@"link"];
}
if ([elementName isEqualToString:@"item"]) {
[feeds addObject:[item copy]];
}
}