2014-01-14 4 views
0

NSString에 html이 저장되어 있습니다. 인터넷에서 다운로드하여 NSXMLParser을 사용하여 구문 분석합니다. 그러나 ó, „, ’ 등의 엔티티에 문제가있는 것으로 보입니다. 큰 문제는 실제로는 실패했다고 말하고 더 이상 파싱을 중지하기 때문에.NSString에서 html 엔티티 제거 - iOS 시뮬레이터와 장치 모두에서 작동하는 솔루션

stackoverflow에서 여러 가지 주제에 대해 좋은 해결책이 있지만 NSString + HTML 카테고리 또는 Mac 용 Google 툴박스 (NSString 카테고리는 GTM 사용)를 사용하는 것이 좋습니다. 이미 GTM을 사용한 프로젝트가 있었고 iOS 시뮬레이터에서 내 앱을 실행할 수 없게 만들었으므로이를 피하고 싶습니다.

+0

도대체 "시뮬레이터에서 응용 프로그램을 빌드 할 수 없게 만든다"는 의미는 –

+0

이전 프로젝트에서 GTM을 사용했을 때 시뮬레이터에서 빌드 할 수 없었지만 장치에서 작동했습니다. – johnyu

+0

질문은 분명하지 않습니다. 당신이 만나는 문제가 무엇인지 분명히해야합니다. –

답변

1

아마도 NSScanner을 사용하여이 방법을 직접 작성하는 것이 가장 쉽습니다. 엔티티 구문은 단순한 대체 목록보다 복잡합니다. 즉, 당신은 지원해야합니다

  • & # D; 여기서 D은 십진수입니다.
  • & # x * H *; H는 16 진수입니다

을 (대문자와 소문자 모두 OK입니다) 그리고 당신은 (a list in the HTML 4 specification 거기) 명명 된 개체에 대한 매핑 테이블이 필요합니다. 매핑의 사전을 초기화 할 수 loadEntityMappingTable()를 구현하고 그것을 작동합니다, 어딘가

static NSDictionary *entityDict; 

if (!entityDict) 
    entityDict = loadEntityMappingTable(); 

NSScanner *scanner = [NSScanner scannerWithString:myHTMLString]; 
NSMutableString *result = [NSMutableString string]; 

[scanner setCharactersToBeSkipped:nil]; // Don’t skip whitespace 

while (![scanner isAtEnd]) { 
    NSString *chunk, *name; 

    if ([scanner scanUpToString:@"&" intoString:chunk]) 
    [result appendString:chunk]; 

    if ([scanner scanString:@"#" intoString:NULL]) { 
    unsigned uch; 
    NSUInteger scanLoc; 
    BOOL hex = NO; 

    // This is a numeric reference 
    if ([scanner scanString:@"x" intoString:NULL]) { 
     hex = YES; 
     scanLoc = [scanner scanLocation]; 
     if (![scanner scanHexInt:&uch]) { 
     // If we fail, show the entire thing in the result string 
     [result appendString:@"&#x"]; 
     continue; 
     } 
    } else { 
     int ich; 
     scanLoc = [scanner scanLocation]; 
     if (![scanner scanInt:&ich]) { 
     // If we fail, show the entire thing 
     [result appendString:@"&#"]; 
     continue; 
     } 

     if (ich < 0) { 
     // Bad Unicode code point 
     [result appendString:@"&#"]; 
     [scanner setScanLocation:scanLoc]; 
     continue; 
     } 

     uch = (unsigned)ich; 
    } 

    // You may also care to prohibit control codes (depending on your application) 
    // i.e. uch < 0x20 || uch >= 0x7f && uch < 0xa0 

    if (uch >= 0xd800 && uch <= 0xdfff || uch > 0x10ffff) { 
     // Bad Unicode code point; show it in the result 
     [result appendString:hex ? @"&#x" : @"&#"]; 
     [scanner setScanLocation:scanLoc]; 
     continue; 
    } 

    if (![scanner scanString:@";" intoString:NULL]) { 
     // Unterminated; show it in the result 
     [result appendString:hex ? @"&#x" : @"&#"]; 
     [scanner setScanLocation:scanLoc]; 
     continue; 
    } 

    if (uch < 0xffff) 
     [result appendFormat:@"%C", uch]; 
    else { 
     unichar lo, hi; 

     hi = 0xd800 | (uch >> 10); 
     lo = 0xdc00 | (uch & 0x3ff); 

     [result appendFormat:@"%C%C", hi, lo]; 
    } 

    continue; 
    } 

    if ([scanner scanUpToString:@";" intoString:&name]) { 
    NSString *ch; 

    if (![scanner scanString:@";" intoString:NULL]) { 
     // Unterminated; show it in the result 
     [result appendFormat:@"&%@", name]; 
     continue; 
    } 

    ch = [entityDict objectForKey:[name lowercaseString]]; 

    if (!ch) { 
     // Unrecognised; show it in the result 
     [result appendFormat:@"&%@;", name]; 
     continue; 
    } 

    [result appendString:ch]; 
    } 
} 

스틱 그 함수 나 방법 :

다음은 시작하는 (스택 오버플로 작성, 테스트되지 않은) 일부 코드입니다.

FWIW 루프와 NSScanner을 사용하는이 일반적인 접근 방식은 스크립팅 언어에서 정규 표현식 일치를 사용하여 처리 할 수있는 비슷한 많은 문제에 쉽게 적용 할 수 있습니다.

관련 문제