2013-02-13 16 views
1

這是我的解析「img src」圖像鏈接的由RSS源生成的形成不良的html的方法體...我知道NSXML只解析XML,但我希望它可以絆倒通過亂七八糟的尋找這些來自凌亂HTML的微小圖像鏈接。iOS NSXMLParsing未形成的HTML

我試圖只檢索在src屬性中找到的第一個圖像鏈接,我在每個元素名稱中找到名爲IMG的nsData,它具有src屬性,然後將它保存到另一個類的NSString * img中。 img標籤並不完全相同,例如nsData的一個實例將只包含一個圖像實例,就像其中的任何一個一樣:

< img class =「ms-rteStyle-photoCredit」src =「www.imagelinkthatineed.com 「東西我不需要

< IMG ALT =」」 SRC = 「www.imagelinkineedfortableimagecellpreview」 東西我不需要

< IMG類= 「MS-rteStyle-photoCredit」 SRC =「www.IneedThisLink.com」更多內容我不需要

似乎生成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 

謝謝你的想法。

+0

在標準的XML中,元素名稱是'img','src'是'attributesDict'返回的屬性,將由'didStartElement'傳遞給你。你能告訴我們你想做什麼嗎(即只是檢索一個img標籤?返回很多?也解析HTML以獲取其他信息)?但'NSXMLParser'不能解析所有的HTML。它解析XML。 – Rob 2013-02-13 20:03:12

+0

對不起,羅布不清楚,我非常感謝你的時間和想法。 我試圖只檢索在src屬性中找到的圖像鏈接,我在每個元素名稱中找到名爲IMG的nsData,它具有src屬性,然後將它保存到另一個類的NSString * img中。 – Morkrom 2013-02-13 20:03:34

+0

我已經用Hpple和NSXMLParser示例更新了我的答案。 – Rob 2013-02-13 22:03:31

回答

7

鑑於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); 
    } 
} 

另外,我說這個支撐自己對於反猛攻NSRegularExpression反應(在我all-time favorite Stack Overflow answer的靜脈),如果你想在一個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。

+1

謝謝你絕對徹底的答案! – Morkrom 2013-02-13 22:14:14

+1

正如你所知,我決定正則表達式,在這種情況下,就我所知,它完美無缺。這是一個巨大的幫助。 – Morkrom 2013-02-22 05:04:21

+0

很好的答案。我採用了Hpple的方法,它的工作原理。這種方法還使得在下載之前檢查圖像的寬度和高度元素變得容易。 – 2014-07-06 22:32:36