【问题标题】:How to parse multiple XML tags using NSXMLParser如何使用 NSXMLParser 解析多个 XML 标签
【发布时间】:2010-11-08 04:01:45
【问题描述】:

我正在解析一个 XML 文件并填充一个表格视图。 XML 的格式如下:

<article>
  <title>Title 1</title>
  <last-modified>MM/DD/YYY</last-modified>
</article>
...

我目前使用NSMutableString 收集所有文章标题并在- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 方法中附加字符串。然后在适当的时候,我将articleTitle 添加到包含所有文章标题的NSMutableArray 中,并按照您的预期从数组中填充表格。

但是,现在我想切换到使用带有副标题的表格视图单元格(我想将最后修改日期作为detailTextLabel,将标题作为textLabel)。通过将解析分为几种方法(即 2 个parser 方法和foundCharacters 方法)的方式,我不确定应该如何“收集”数据,并从该数据中填充表格。

最好的方法是什么?我可以以某种方式填写一个 NSDictionary 之类的东西,然后在构建表格单元格时按键检索项目吗?

我似乎想不出解决这个问题的最佳方法。

提前致谢!

【问题讨论】:

  • 事件驱动的 XML 解析很牛逼,如果有可用的 DOM 样式解析器,从那里开始。

标签: iphone objective-c ios nsxmlparser


【解决方案1】:

如果你愿意,你可以使用 DOM 解析器,它可能会让你的生活更轻松,但如果出于某种原因你想坚持使用 NSXMLParser,请继续阅读。

你希望你给解析器的对象作为你的委托(实现 NSXMLParserDelegate 的东西)基本上在传递数据时积累数据。

经常被忽视的重要细节:对于各种标签的“内容”,您实际上可以收到多次对parser:foundCharacters: 的调用。绝对没有要求解析器一次将所有内容都交给您。如果它愿意,它可以一次向您发送一个字符,而您必须妥善处理它。

以下假设有以下 ivars:

NSMutableArray articles_;
NSMutableString currentCharacters_;
Article currentArticle_; // Article has title and lastModified properties.

下面是委托如何实现一些相关消息的示例(以下代码显然没有错误处理):

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if ([elementName isEqualToString:@"article"]) {
        NSAssert(currentArticle_ == nil, @"Uh oh! Bad XML!");
        currentArticle_ = [[Article alloc] init];
        return;
    }
    if ([elementName isEqualToString:@"title"]) {
        NSAssert(currentCharacters_ == nil, @"Uh oh! Bad XML!");
        currentCharacters_ = [[NSMutableString alloc] init];
        return;
    }
    if ([elementName isEqualToString:@"last-modified"]) {
        NSAssert(currentCharacters_ == nil, @"Uh oh! Bad XML!");
        currentCharacters_ = [[NSMutableString alloc] init];
        return;
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    if ([elementName isEqualToString:@"article"]) {
        [articles_ addObject:currentArticle_];
        [currentArticle_ release], currentArticle_ = nil;
        return;
    }
    if ([elementName isEqualToString:@"title"]) {
        currentArticle_.title = currentCharacters_;
        [currentCharacters_ release], currentCharacters_ = nil;
        return;
    }
    if ([elementName isEqualToString:@"last-modified"]) {
        [currentArticle_ setLastModifiedWithString:currentCharacters_];
        [currentCharacters_ release], currentCharacters_ = nil;
        return;
    }
}

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

【讨论】:

  • 完美,正是我需要的!谢谢。
  • 如果这正是您所需要的,请随时接受答案。 ;)
【解决方案2】:

你可以阅读官方Event-Driven XML Programming Guidetutorial

我也可以建议尝试touchXML 而不是 NSXMLParser

【讨论】:

    【解决方案3】:

    我使用的是 DOM Parser,如果您不解析大量数据,它会更干净、更容易。推荐 Google 的 GDATA

    上面有一个StackOverflow Question

    NSError *error;
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
    if (doc == nil) { return nil; }
    
    // get number of hits
    GDataXMLElement * article = [[doc nodesForXPath:@"//article" error:nil] objectAtIndex:0];
    
    // title
    NSLog([[[entry elementsForName:@"title"] objectAtIndex:0] stringValue]], nil);
    
    // last-modified
    NSLog([[[entry elementsForName:@"last-modified"] objectAtIndex:0] stringValue]], nil);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-13
      • 2012-09-02
      相关资源
      最近更新 更多