【问题标题】:iOS NSXMLParsing unformed HTMLiOS NSXMLParsing unformed HTML
【发布时间】:2013-02-13 19:41:53
【问题描述】:

这是我的方法体,用于从 RSS 提要生成的格式不正确的 html 中解析“img src”图像链接...我知道 NSXML 仅解析 XML,但我希望它可以偶然发现从凌乱的 html 中找到这些微小的图像链接。

我试图仅检索在 src 属性中找到的第一个图像链接,我在具有 src 属性的 nsData 中名为 IMG 的每个元素名称中找到,然后将其保存到另一个类中的 NSString *img 中。 img 标签并不完全相同,例如 nsData 的一个实例将只包含一个图像实例,例如以下任何一个:

我不需要的东西

我不需要的东西

更多我不需要的东西

似乎生成 NSLog 输出的唯一类是第一个类。

如何让解析器方法真正运行?

鉴于有一种方法,您是否推荐一种不同的、更简单的方法?

#import "HtmlParser.h"
#import "ArticleItem.h"

@implementation HtmlParser
@synthesize elementArray;

- (HtmlParser *) InitHtmlByString:(NSString *)string {
//    NSString *description = [NSString string];
NSData *nsData = [[NSData alloc] initWithContentsOfFile:(NSString *)string];
elementArray = [[NSMutableArray alloc] init];
parser = [[NSXMLParser alloc] initWithData:nsData];
parser.delegate = self;
[parser parse];

如果我 NSLog(@"%@", nsData);在这个方法体中,输出会输出原始 HTML。

currentHTMLElement = [ArticleItem alloc];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"img src"]) {
    currentHTMLElement = [[ArticleItem alloc] init];
}
NSLog(@"\t%@ found a %@ element", self, elementName);
}
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (!currentHTMLElement)
    currentHTMLElement = [[NSMutableString alloc] initWithString:string];   
NSLog(@"Processing Value: %@", currentHTMLElement);
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName   
{
if ([elementName isEqualToString:@"img src"])
    {
        currentHTMLElement.img = elementName;
        [elementArray addObject:currentHTMLElement];
        currentHTMLElement = nil;
        currentNodeContent = nil;
    }
else
{
    if (currentHTMLElement !=nil && elementName != nil && ([elementName isEqualToString:@"img src"]))
    {
        [currentHTMLElement setValue:currentHTMLElement forKey:elementName];
    }
}
    currentHTMLElement = nil;
}                
@end

感谢您的意见。

【问题讨论】:

  • 在标准 XML 中,元素名称是 img,src 是 attributesDict 返回的属性,将由 didStartElement 传递给您。你能告诉我们你想要做什么(即只检索一个 img 标签?返回很多?也解析 HTML 以获取其他信息)?但NSXMLParser 无法解析所有 HTML。它解析 XML。
  • 抱歉不清楚 Rob,非常感谢您的时间和想法。我试图只检索在 src 属性中找到的图像链接,我在 nsData 中名为 IMG 的每个元素名称中找到了具有 src 属性的图像链接,然后将其保存到另一个类中的 NSString *img 中。
  • 我已经用 Hpple 和 NSXMLParser 示例更新了我的答案。

标签: iphone html ios nsxmlparser


【解决方案1】:

鉴于 HTML 通常不是格式良好的 XML,NSXMLParser 可能不起作用。如果你想解析 HTML,你可以参考这篇 Ray Wenderlich 的文章,How to Parse HTML on iOS。如果您已按照这些说明操作并将 Hpple 添加到您的项目中,则可以检索图像 src 属性,如下所示:

#import "TFHpple.h"

- (void)retrieveImageSourceTagsViaHpple:(NSURL *)url
{
    NSData *data = [NSData dataWithContentsOfURL:url];

    TFHpple *parser = [TFHpple hppleWithHTMLData:data];

    NSString *xpathQueryString = @"//img";
    NSArray *nodes = [parser searchWithXPathQuery:xpathQueryString];

    for (TFHppleElement *element in nodes)
    {
        NSString *src = [element objectForKey:@"src"];
        NSLog(@"img src: %@", src);
    }
}

另外,如果你想在 html 文件中列出 img 标记列表,我会说这是为反NSRegularExpression 响应的猛攻做好准备(在我的all-time favorite Stack Overflow answer 的脉络中),你可以使用以下有点复杂的正则表达式:

- (void)retrieveImageSourceTagsViaRegex:(NSURL *)url
{
    NSString *string = [NSString stringWithContentsOfURL:url
                                                encoding:NSUTF8StringEncoding
                                                   error:nil];

    NSError *error = NULL;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(<img\\s[\\s\\S]*?src\\s*?=\\s*?['\"](.*?)['\"][\\s\\S]*?>)+?"
                                                                           options:NSRegularExpressionCaseInsensitive
                                                                             error:&error];

    [regex enumerateMatchesInString:string
                            options:0
                              range:NSMakeRange(0, [string length])
                         usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {

                             NSString *src = [string substringWithRange:[result rangeAtIndex:2]];
                             NSLog(@"img src: %@", src);
                         }];
}

如果你想使用NSXMLParser,它看起来像这样:

- (void)retrieveImageSourceTagsViaNSXMLParser:(NSURL *)url
{
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
    parser.delegate = self;
    [parser parse];
}

#pragma mark - NSXMLParserDelegate methods

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"img"])
    {
        NSString *src = attributeDict[@"src"];

        NSLog(@"img src: %@", src);
    }
}

问题是,根据我的经验,NSXMLParser 在解析 HTML 方面不如 LibXML2/Hpple 成功。我发现在一些简单的页面上,上面的效果很好。但在其他情况下,它不会。归根结底,虽然NSXMLParser 擅长解析格式良好的 XML,但我会谨慎使用它来解析 HTML。

【讨论】:

  • 感谢您绝对彻底的回答!
  • 正如你所知,我决定使用正则表达式,据我所知,在这种情况下它完美无缺。这是一个巨大的帮助。
  • 好答案。我采用了 Hpple 方法,它很有效。这种方法还可以在下载之前轻松检查图像的宽度和高度元素。
猜你喜欢
  • 1970-01-01
  • 2013-07-02
  • 1970-01-01
  • 2016-02-15
  • 2013-12-17
  • 2011-11-27
  • 2015-09-27
  • 2016-09-26
相关资源
最近更新 更多