2013-05-20 1 views
3

저는 iOS 개발에서 새로운데, 현재 NSXMLparser를 구현했지만 실제로는 같은 이름의 태그를 분리하는 방법을 알지 못합니다. 콘텐츠 (예 : <description>). 일부 피드의 경우이 태그에는 요약 만 표시되고 다른 태그에는 추출 할 "img src"가 포함되어 있습니다.NSXMLParser에서이 메서드를 구현하여 이미지를 추출하는 방법

Example of description tags wich i need to grab the images and then pass to my UIImageView: 

<description><![CDATA[ <p>Roger Craig Smith and Troy Baker to play Batman and the Joker respectively in upcoming action game; Deathstroke confirmed as playable character. </p><p><img src="http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg" 

<description>&lt;img src=&quot;http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg&quot; width=&quot;70&quot; height=&quot;92&quot; hspace=&quot;3&quot; alt=&quot;&quot; border=&quot;0&quot; align=left style="background:#333333;padding:0px;margin:0px 4px 0px 0px;border-style:solid;border-color:#aaaaaa;border-width:1px" /&gt; &lt;p&gt; 

(또는 CDATA없이) 내가 @ 롭 example 내 사건을 해결한다고 생각하지만 난 데이터와 이미지를 분리하기 위해, 아래에 설명 내 NSXMLParser에 포함하는 방법을 모르겠어요. 이 파서에서 데이터 (요약) 만 잡을 수 있습니다.

내 NSXMLParser : 당신은 그냥 그 안에 포함 된 img 태그가 두 description 요소, 각이 당신의 예에서

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict 
{ 
element = [elementName copy]; 


if ([elementName isEqualToString:@"item"]) 
{ 
    elements = [[NSMutableDictionary alloc] init]; 
    title = [[NSMutableString alloc] init]; 
    date = [[NSMutableString alloc] init]; 
    summary = [[NSMutableString alloc] init]; 
    link = [[NSMutableString alloc] init]; 
    img = [[NSMutableString alloc] init]; 
    imageLink = [[NSMutableString alloc]init]; 

} 

if([elementName isEqualToString:@"media:thumbnail"]) { 
    NSLog(@"thumbnails media:thumbnail: %@", attributeDict); 
    imageLink = [attributeDict objectForKey:@"url"]; 
} 

if([elementName isEqualToString:@"media:content"]) { 
    NSLog(@"thumbnails media:content: %@", attributeDict); 
    imageLink = [attributeDict objectForKey:@"url"]; 

} 

if([elementName isEqualToString:@"enclosure"]) { 
    NSLog(@"thumbnails Enclosure %@", attributeDict); 
    imageLink = [attributeDict objectForKey:@"url"]; 
} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
if ([element isEqualToString:@"title"]) 
{ 
    [title appendString:string]; 
} 
else if ([element isEqualToString:@"pubDate"]) 
{ 
    [date appendString:string]; 
} 
else if ([element isEqualToString:@"description"]) 
{ 
    [summary appendString:string]; 

} 
    else if ([element isEqualToString:@"media:description"]) 
{ 
    [summary appendString:string]; 

} 
else if ([element isEqualToString:@"link"]) 
{ 
    [link appendString:string]; 
} 
else if ([element isEqualToString:@"url"]) { 

    [imageLink appendString:string]; 
} 
else if ([element isEqualToString:@"src"]) { 

    [imageLink appendString:string]; 
} 
else if ([element isEqualToString:@"content:encoded"]){ 
    NSString *imgString = [self getImage:string]; 
    if (imgString != nil) { 
     [img appendString:imgString]; 
     NSLog(@"Content of img:%@", img); 
    } 

} 

-(NSString *) getImage:(NSString *)htmlString { 
NSString *url = nil; 

NSScanner *theScanner = [NSScanner scannerWithString:htmlString]; 

[theScanner scanUpToString:@"<img" intoString:nil]; 
if (![theScanner isAtEnd]) { 
    [theScanner scanUpToString:@"src" intoString:nil]; 
    NSCharacterSet *charset = [NSCharacterSet characterSetWithCharactersInString:@"\"'"]; 
    [theScanner scanUpToCharactersFromSet:charset intoString:nil]; 
    [theScanner scanCharactersFromSet:charset intoString:nil]; 
    [theScanner scanUpToCharactersFromSet:charset intoString:&url]; 

} 
return url; 
} 

@end 

답변

2

. 그냥 정상적으로 description을 구문 분석 한 다음 img 태그를 꺼냅니다 (정규식을 사용하여 아래 retrieveImageSourceTagsViaRegex을 사용하거나 스캐너 사용).

원하지 않는 경우 CDATACDATA의 표현을 다르게 처리 할 필요가 없습니다. NSXMLParserDelegatefoundCDATA 루틴을 제공하지만 실제로는 이 아니며이 구현됩니다. foundCDATA이 없으면 foundCharacters 루틴 NSXMLParserCDATA 태그가있는 description 태그의 변환을 원활하게 처리합니다. 다음 파서 밖으로 그들의 이미지의 URL을 잡아, 그 description 항목을 모두 구문 분석

<xml> 
    <descriptions> 
     <description><![CDATA[ <p>Roger Craig Smith and Troy Baker to play Batman and the Joker respectively in upcoming action game; Deathstroke confirmed as playable character. </p><p><img src="http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg">]]></description> 
     <description>&lt;img src=&quot;http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg&quot; width=&quot;70&quot; height=&quot;92&quot; hspace=&quot;3&quot; alt=&quot;&quot; border=&quot;0&quot; align=left style="background:#333333;padding:0px;margin:0px 4px 0px 0px;border-style:solid;border-color:#aaaaaa;border-width:1px" /&gt; &lt;p&gt;</description> 
    </descriptions> 
</xml> 

:

는 다음과 같은 가상의 XML을 고려하십시오.

@interface ViewController() <NSXMLParserDelegate> 

@property (nonatomic, strong) NSMutableString *description; 
@property (nonatomic, strong) NSMutableArray *results; 

@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 

    NSURL *filename = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"xml"]; 
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:filename]; 
    parser.delegate = self; 
    [parser parse]; 

    // full array of dictionary entries 

    NSLog(@"results = %@", self.results); 
} 

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

    NSMutableArray *results = [NSMutableArray array]; 

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

          [results addObject:[string substringWithRange:[result rangeAtIndex:2]]]; 
         }]; 

    return results; 
} 

#pragma mark - NSXMLParserDelegate 

- (void)parserDidStartDocument:(NSXMLParser *)parser 
{ 
    self.results = [NSMutableArray array]; 
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{ 
    if ([elementName isEqualToString:@"description"]) 
     self.description = [NSMutableString string]; 
} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
    if (self.description) 
     [self.description appendString:string]; 
} 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 
    if ([elementName isEqualToString:@"description"]) 
    { 
     NSArray *imgTags = [self retrieveImageSourceTagsViaRegex:self.description]; 
     NSDictionary *result = @{@"description": self.description, @"imgs" : imgTags}; 
     [self.results addObject:result]; 
     self.description = nil; 
    } 
} 

@end 

다음과 같은 결과를 산출한다 (참고, 아니 CDATA) : 당신이 볼 수 있듯이, 필요 CDATA에 대한 특별한 취급이없는 그래서

results = (
     { 
     description = " <p>Roger Craig Smith and Troy Baker to play Batman and the Joker respectively in upcoming action game; Deathstroke confirmed as playable character. </p><p><img src=\"http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg\">"; 
     imgs =   (
      "http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg" 
     ); 
    }, 
     { 
     description = "<img src=\"http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg\" width=\"70\" height=\"92\" hspace=\"3\" alt=\"\" border=\"0\" align=left style=\"background:#333333;padding:0px;margin:0px 4px 0px 0px;border-style:solid;border-color:#aaaaaa;border-width:1px\" /> <p>"; 
     imgs =   (
      "http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg" 
     ); 
    } 
) 

, 결론, 단지를 구문 분석 정상적인 XML처럼 CDATA에 대해 걱정하지 말고 NSScanner 또는 NSRegularExpression을 사용하여 이미지 URL을 구문 분석하면됩니다.

+0

미안하지만, 나는 XML 데이터에서 description 태그의 이미지가 CDATA 안에 있고 다른 이미지가 아니라는 것을 알았습니다. 위의 설명 태그의 예는 다른 RSS 피드에서 왔으며 두 개의 설명 태그가있는 XML 파일 하나가 아닙니다. 내 NSXMLParser에서 foundCDATA 메서드를 구현할 때 분명히 내 요약을 덮어 쓰고 "img src"이미지를 가져 오지만 둘 다 필요합니다. 여기 내 파서를 참조하십시오 [link] (https://dl.dropboxusercontent.com/u/1216970/RSSParser.rtf) 감사합니다. 정말로 도움을 주셔서 감사합니다. – Edward

+0

@Edward'foundCDATA'를 전혀 구현할 필요가 없습니다. 그렇게하지 않으면, 표준'foundCharacters'가 자동으로 그것을 해석하여'CDATA' 문자를 올바르게 추출합니다 (그러나'CDATA' 열기 태그와 닫기 태그는 제거합니다).특히 때로는'CDATA'와 가끔씩 혼용되는 경우'foundCDATA'를 구현하지 말고'foundCharacters'는 둘 다 꽤 정상적으로 처리 할 것입니다. 내 구현을 참조하십시오. 하나의'description' 태그는'CDATA'를 가지지 만 다른 하나는 완벽하게 파싱 된 표준'foundCharacter'를 가지고 있습니다. – Rob

+0

채팅으로 이동해보십시오. http://chat.stackoverflow.com/rooms/30287/chat-with-edward – Rob