2013-03-22 4 views
1

im은 ios 개발에서 매우 새롭고 RSS 파일 (xml)을 구문 분석하려고합니다. 내가 아이폰에 아주 새로운 해요 말했듯이NSXMLParser는 CDATA를 무시하지 않습니다

- (void)parserDidStartDocument:(NSXMLParser *)parser 
    { 
     self.titles = [[NSMutableArray alloc]init]; 
     self.descriptions = [[NSMutableArray alloc]init]; 
     self.links = [[NSMutableArray alloc]init]; 
    } 

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

    if ([elementName isEqualToString:@"title"]) { 
     isTitle=YES; 
     self.titlesString = [[NSMutableString alloc]init]; 
    } 

    if ([elementName isEqualToString:@"description"]) { 
     isDesription = YES; 
     self.descriptionString = [NSMutableString string]; 
     self.data = [NSMutableData data]; 
    } 



} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ 
    if(isItem && isTitle){ 
     [self.titlesString appendString:string]; 
    } 
    if (isItem && isDesription) { 
     if (self.descriptionString) 
      [self.descriptionString appendString:string]; 
    } 






} 

- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock 
{ 
    if (self.data) 
     [self.data appendData:CDATABlock]; 

} 


- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 
    if ([elementName isEqualToString:@"item"]) { 
     isItem = NO; 
     [self.titles addObject:self.titlesString]; 

     [self.descriptions addObject:self.descriptionString]; 


    } 

    if ([elementName isEqualToString:@"title"]) { 
     isTitle=NO; 

    } 
    if ([elementName isEqualToString:@"description"]) { 

     NSString *result = [self.descriptionString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
     NSLog(@"string=%@", result); 


     if ([self.data length] > 0) 
     { 
      NSString *htmlSnippet = [[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]; 
      NSString *imageSrc = [self firstImgUrlString:htmlSnippet]; 
      NSLog(@"img src=%@", imageSrc); 
      [self.links addObject:imageSrc]; 
     } 



     self.descriptionString = nil; 
     self.data = nil; 
    } 


} 

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

    NSTextCheckingResult *result = [regex firstMatchInString:string 
                options:0 
                 range:NSMakeRange(0, [string length])]; 

    if (result) 
     return [string substringWithRange:[result rangeAtIndex:2]]; 

    return nil; 
} 

@end 

:

<item> 
<category> General </category > 
<title> killed in a tractor accident , was critically injured windsurfer </ title> 
<description> 
< ! [ CDATA [ 
<div> <a href='http://www.ynet.co.il/articles/0,7340,L-4360016,00.html'> <img src = 'http://www.ynet.co. il/PicServer3/2012/11/28/4302844/YOO_8879_a.jpg ' alt =' photo: Yaron Brener 'title =' Amona 'border = '0' width = '116 'height = '116'> </ a> </div > 
] ] > 
Tractor driver in his 50s near Kfar Yuval flipped and trapped underneath . Room was critically injured windsurfer hurled rocks because of strong winds and wind surfer after was moderately injured in Netanya 
</description > 
<link> 
http://www.ynet.co.il/articles/0 , 7340, L- 4360016 , 00.html 
</link > 
<pubDate> Fri, 22 Mar 2013 17:10:15 +0200 </ pubDate> 
<guid> 
http://www.ynet.co.il/articles/0 , 7340, L- 4360016 , 00.html 
</guid > 
<tags> Kill , car accidents , surfing </tags > 
</item > 

여기 내 XmlParser가 코드 (언어에 대한 죄송) : 여기

은 XML이다 개발, 나는 그것을 몇 시간 동안 풀 수있는 방법을 찾았지만 아무 것도 발견하지 못했습니다. 주제를 연 다음 몇 가지 질문을하기로했습니다.

하나. 파서는 CDATA가 모든 것을 파싱하는 것을 무시하지 않습니다. 왜 이런 일이 발생합니까? 당신이 볼 수 있듯이 그 자체가 cdata가 아니고 나는 첫 번째 단계 만 가지고 있지만 foundCDATA를 사용하지 않을 때에도 나머지는 얻을 수 있습니다 : (NSData *) CDATABlock

이미지 링크를 가져 가고 싶습니다. 어떻게해야합니까? 나는 온라인으로 검색했고 많은 가이드가 오직 foundCDATA 함수를 사용한다고 설명했다. (NSData *) CDATABlock 그러나 어떻게 사용 되는가? 코드에서 사용한 방식은 무엇입니까?

이해해 주실 수 있도록 설명해주세요. 고마워요! 당신이 질문에 대한 대답에서

+0

어떻게 다시 얻을 수 있습니까? 해당 이미지 소스에 대한 성문 표현 패턴 –

답변

1

: 당신이 foundCDATA을 구현 한 경우

  1. 이 파서는, 그 방법에 description CDATA를 구문 분석, 그리고 foundCharacters에있는 것입니다 것입니다. 반면에 foundCDATA을 구현하지 않은 경우 CDATAfoundCharacters으로 구문 분석됩니다. 따라서 foundCharacters에서 CDATA을 구문 분석하지 않으려면 foundCDATA을 구현해야합니다.

  2. img URL을 추출하려면 어떻게 든받은 HTML을 구문 분석해야합니다. 당신은 Hpple를 사용할 수 있지만, 난 그냥 정규 표현식을 사용하는 경향이있을 수 있습니다 : 예를 들어


:

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

    NSTextCheckingResult *result = [regex firstMatchInString:string 
                options:0 
                 range:NSMakeRange(0, [string length])]; 

    if (result) 
     return [string substringWithRange:[result rangeAtIndex:2]]; 

    return nil; 
} 

이 또한 내가 모두 Hpple 및 정규식 솔루션을 설명하는 this other Stack Overflow answer 참조 설명을 구문 분석하고 텍스트 (CDATA는 제외)를 한 필드에 넣고 CDATA의 이미지 URL을 다른 변수에 넣는 방법은 NSXMLParserDelegate입니다. 당신은 당신의 과정을 수용 할 수 있도록 수정해야 할 것이다, 그러나 희망이 당신에게 기본적인 아이디어 제공 :

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

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 
{ 
    NSLog(@"%s, parseError=%@", __FUNCTION__, parseError); 
} 

// In my standard NSXMLParser routine, I leave self.string `nil` when not parsing 
// a particular element, and initialize it if I am parsing. I do it this way 
// so only my `didStartElement` and `didEndElement` need to worry about the particulars 
// and my `foundCharacters` and `foundCDATA` are simplified. But do it however you 
// want. 

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

- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock 
{ 
    if (self.data) 
     [self.data appendData:CDATABlock]; 
} 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 
    if ([elementName isEqualToString:@"description"]) 
    { 
     // get the text (non-CDATA) portion 

     // you might want to get rid of the leading and trailing whitespace 

     NSString *result = [self.string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
     NSLog(@"string=%@", result); 

     // get the img out of the CDATA 

     if ([self.data length] > 0) 
     { 
      NSString *htmlSnippet = [[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]; 
      NSString *imageSrc = [self firstImgUrlString:htmlSnippet]; 
      NSLog(@"img src=%@", imageSrc); 
     } 

     // once I've saved the data where I want to save it, I `nil` out my 
     // `string` and `data` properties: 

     self.string = nil; 
     self.data = nil; 
    } 
} 
+0

먼저 답을 주셔서 감사합니다. 하지만 왜 im은 "description"의 모든 텍스트를 getin으로 구현하지 않았는데도 findCDATA는 구현되지 않았습니다. 파서가 CDATA를 건너 뛰지 않으면 안됩니까? 텍스트 만 필요하면 Hipple을 사용하여 이미지 URL을 가져옵니다. 당신이 저를 이해하기를 바랍니다. 다시 감사드립니다! – OshriALM

+0

@ user1600694 당신이 무엇을 성취하려고하는지 잘 모르겠지만 XML을 파싱 할 때'found ...'메소드는 열리고 닫히는'description' 태그 사이의 모든 데이터를보고합니다. 유일한 질문은'foundCharacters'와'foundCDATA' (이 경우,'description' 태그의 두 부분이 따로 반환 될 것입니다) 또는'foundCharacters' 태그 (이 경우에 열린 닫는 태그는'foundCharacters'에 의해 반환됩니다). 당신은 "왜 나는 모든 텍스트를 얻고 있는가?"라고 묻는다. 그것은 파서가 작동하는 방식입니다. – Rob

+0

'CDATA'를 버리거나'img'의'src'를 파싱하고 나머지는 버리길 원한다면'foundCDATA'를 구현하십시오 (이 경우'foundCharacters'는 CDATA를 제외시킬 것입니다). CDATA로 원하는대로하십시오. – Rob

0

대답 1 : 나는이 질문에 대한 롭에 의해 주어진 답과 함께 갈 것입니다.

답변 2 : 이미지 링크를 얻으려면이 방법을 사용해보십시오 ....

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{ 
    if([currentElement isEqualToString:@"img"]) { 
     NSLog(@"%@",[attributeDict objectForKey:@"src"]); 
    } 
} 
+0

2 번째 점에서, img 태그가 XML 태그 인 경우에는 정확합니다. 슬프게도, 그것은 CDATA 내부에 있는데, NSXMLParser는 구문 분석하지 않습니다 (도 마찬가지입니다). 이것이 XML로 파싱되지 않도록 콘텐츠에 플래그를 지정하는 CDATA의 모든 목적입니다. – Rob

0

추출 할 이미지 링크는 CDATA 블록 안에 있지만 rss 파서는 CDATA 블록을 무시합니다.

당신은 CDATA에서 문자열을 추출해야하는 경우 foundCDATA이 블록을 사용할 수 있습니다 : 지금

- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock 
    { 

    NSMutableString *cdstring = [[NSMutableString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding]; 
    } 

의 MutableString "cdstring"를 포함한다 :

<div> 
    <a href='http://www.ynet.co.il/articles/0,7340,L-4360016,00.html'> 
    <img src='http://www.ynet.co. il/PicServer3/2012/11/28/4302844/YOO_8879_a.jpg ' alt=' photo: Yaron Brener ' title=' Amona ' border='0' width='116 ' height='116'> 
    </ a> 
    </ div> 
    ]]> 

을 지금 바로 검색 href = 'stringcontainsstring을 사용하여 링크를 추출하거나 webview를 사용하여 표시

htmlContent = [NSString stringWithFormat:@"%@", cdstring]; 
    [webView loadHTMLString:htmlContent baseURL:nil]; 
관련 문제