1

This is my method body for parsing "img src" image links from poorly formed html generated by an RSS feed... I am aware that NSXML only parses XML, but I have this hope that it can stumble through the mess to find these miniscule image links from messy html.

I'm trying to retrieve ONLY the FIRST image link found in the src attribute I find in each element name called IMG in nsData that has a src attribute and then save it to a NSString *img in another class. The img tags are not all the same, for instance an instance of nsData will contain only one image instance like any one of these:

< img class="ms-rteStyle-photoCredit" src="www.imagelinkthatineed.com" stuff I don't need

< img alt="" src="www.imagelinkineedfortableimagecellpreview" stuff I don't need

< img class="ms-rteStyle-photoCredit" src="www.IneedThisLink.com" more stuff I don't need

The only class that seems to generate NSLog output is the first one.

How can I get the parser methods to actually run ?

Given that there's a way, is there a different, simpler way you recommend?

#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];

If I NSLog(@"%@", nsData); in this method body, the output spits out the raw 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

Thank you for your thoughts.

4

1 回答 1

7

鉴于 HTML 通常不是格式良好的 XML,NSXMLParser可能无法正常工作。如果你想解析 HTML,你可以参考 Ray Wenderlich 的这篇文章,如何在 iOS 上解析 HTML。如果您已按照这些说明操作并将 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);
    }
}

或者,我说这为反响应的冲击做好了准备(在我一直最喜欢的 Stack Overflow 答案NSRegularExpression的脉络中),如果你想要一个html 文件中的标签列表,你可以使用以下有点复杂的常规表达:img

- (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。

于 2013-02-13T20:36:43.873 回答