2012-11-08 5 views
5

Ich verwende eine Open-Source-Methode, die den HTML-Text in einen NSString analysiert.Open-Source-HTML-Parsing-Klasse Parsing Leerzeichen zwischen Absätzen nicht korrekt

Die resultierenden Zeichenfolgen weisen zwischen den ersten paar Absätzen große Leerräume auf, aber nur eine Leerzeile für nachfolgende Absätze. Hier ist ein Beispiel für eine Ausgabe.

enter image description here Unten ist die Methode, die ich anrufe. Ich habe nur zwei Zeilen des Codes geändert. Für stopCharacters und newLineAndWhitespaceCharacters entfernte ich /n aus dem Zeichensatz, denn wenn es enthalten war, war der gesamte Text ein langer Absatz.

- (NSString *)stringByConvertingHTMLToPlainText { 

    // Pool 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    // Character sets 
    NSCharacterSet *stopCharacters = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@"< \t\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]]; 
    NSCharacterSet *newLineAndWhitespaceCharacters = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@" \t\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]]; 
    NSCharacterSet *tagNameCharacters = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]; 

    // Scan and find all tags 
    NSMutableString *result = [[NSMutableString alloc] initWithCapacity:self.length]; 
    NSScanner *scanner = [[NSScanner alloc] initWithString:self]; 
    [scanner setCharactersToBeSkipped:nil]; 
    [scanner setCaseSensitive:YES]; 
    NSString *str = nil, *tagName = nil; 
    BOOL dontReplaceTagWithSpace = NO; 
    do { 

     // Scan up to the start of a tag or whitespace 
     if ([scanner scanUpToCharactersFromSet:stopCharacters intoString:&str]) { 
      [result appendString:str]; 
      str = nil; // reset 
     } 

     // Check if we've stopped at a tag/comment or whitespace 
     if ([scanner scanString:@"<" intoString:NULL]) { 

      // Stopped at a comment or tag 
      if ([scanner scanString:@"!--" intoString:NULL]) { 

       // Comment 
       [scanner scanUpToString:@"-->" intoString:NULL]; 
       [scanner scanString:@"-->" intoString:NULL]; 

      } else { 

       // Tag - remove and replace with space unless it's 
       // a closing inline tag then dont replace with a space 
       if ([scanner scanString:@"/" intoString:NULL]) { 

        // Closing tag - replace with space unless it's inline 
        tagName = nil; dontReplaceTagWithSpace = NO; 
        if ([scanner scanCharactersFromSet:tagNameCharacters intoString:&tagName]) { 
         tagName = [tagName lowercaseString]; 
         dontReplaceTagWithSpace = ([tagName isEqualToString:@"a"] || 
                [tagName isEqualToString:@"b"] || 
                [tagName isEqualToString:@"i"] || 
                [tagName isEqualToString:@"q"] || 
                [tagName isEqualToString:@"span"] || 
                [tagName isEqualToString:@"em"] || 
                [tagName isEqualToString:@"strong"] || 
                [tagName isEqualToString:@"cite"] || 
                [tagName isEqualToString:@"abbr"] || 
                [tagName isEqualToString:@"acronym"] || 
                [tagName isEqualToString:@"label"]); 
        } 

        // Replace tag with string unless it was an inline 
        if (!dontReplaceTagWithSpace && result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "]; 

       } 

       // Scan past tag 
       [scanner scanUpToString:@">" intoString:NULL]; 
       [scanner scanString:@">" intoString:NULL]; 

      } 

     } else { 

      // Stopped at whitespace - replace all whitespace and newlines with a space 
      if ([scanner scanCharactersFromSet:newLineAndWhitespaceCharacters intoString:NULL]) { 
       if (result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "]; // Dont append space to beginning or end of result 
      } 

     } 

    } while (![scanner isAtEnd]); 

    // Cleanup 
    [scanner release]; 

    // Decode HTML entities and return 
    NSString *retString = [[result stringByDecodingHTMLEntities] retain]; 
    [result release]; 

    // Drain 
    [pool drain]; 

    // Return 
    return [retString autorelease]; 

} 

EDIT:

Hier ist die NSLog der Zeichenfolge. Ich klebte nur die ersten paar Absätze

Mitt Romney spent the past six years running for president. After his loss to President Barack Obama, he'll have to chart a different course. 


His initial plan: spend time with his family. He has five sons and 18 grandchildren, with a 19th on the way. 






"I don't look at postelection to be a time of regrouping. Instead it's a time of forward focus," Romney told reporters aboard his plane Tuesday evening as he returned to Boston after the final campaign stop of his political career. "I have, of course, a family and life important to me, win or lose." 

The most visible member of that family — wife Ann Romney — says neither she nor her husband will seek political office again. 

etc ....

for (int j = 25; j< 50; j++) { 
    char test = [completeTrimmed characterAtIndex:([completeTrimmed rangeOfString:@"chart a different course."].location + j)]; 

     NSLog(@"%hhd", test); 
    } 

012-11-11 17:15:57.668 LMU_LAL_LAUNCHER[5431:c07] 32 
2012-11-11 17:15:57.669 LMU_LAL_LAUNCHER[5431:c07] 32 
2012-11-11 17:15:57.669 LMU_LAL_LAUNCHER[5431:c07] 10 
2012-11-11 17:15:57.670 LMU_LAL_LAUNCHER[5431:c07] 32 
2012-11-11 17:15:57.670 LMU_LAL_LAUNCHER[5431:c07] 32 
2012-11-11 17:15:57.670 LMU_LAL_LAUNCHER[5431:c07] 10 
2012-11-11 17:15:57.671 LMU_LAL_LAUNCHER[5431:c07] 32 
2012-11-11 17:15:57.671 LMU_LAL_LAUNCHER[5431:c07] 32 
2012-11-11 17:15:57.671 LMU_LAL_LAUNCHER[5431:c07] 10 
2012-11-11 17:15:57.672 LMU_LAL_LAUNCHER[5431:c07] 32 
2012-11-11 17:15:57.672 LMU_LAL_LAUNCHER[5431:c07] 72 
2012-11-11 17:15:57.672 LMU_LAL_LAUNCHER[5431:c07] 105 
2012-11-11 17:15:57.673 LMU_LAL_LAUNCHER[5431:c07] 115 
2012-11-11 17:15:57.673 LMU_LAL_LAUNCHER[5431:c07] 32 
2012-11-11 17:15:57.673 LMU_LAL_LAUNCHER[5431:c07] 105 
2012-11-11 17:15:57.673 LMU_LAL_LAUNCHER[5431:c07] 110 
2012-11-11 17:15:57.674 LMU_LAL_LAUNCHER[5431:c07] 105 
2012-11-11 17:15:57.674 LMU_LAL_LAUNCHER[5431:c07] 116 
2012-11-11 17:15:57.674 LMU_LAL_LAUNCHER[5431:c07] 105 
2012-11-11 17:15:57.675 LMU_LAL_LAUNCHER[5431:c07] 97 
2012-11-11 17:15:57.675 LMU_LAL_LAUNCHER[5431:c07] 108 
2012-11-11 17:15:57.675 LMU_LAL_LAUNCHER[5431:c07] 32 
2012-11-11 17:15:57.675 LMU_LAL_LAUNCHER[5431:c07] 112 
2012-11-11 17:15:57.676 LMU_LAL_LAUNCHER[5431:c07] 108 
2012-11-11 17:15:57.676 LMU_LAL_LAUNCHER[5431:c07] 97 
+0

Wahrscheinlich müssen Sie die stringByReplacingCharactersInRange-Methode verwenden, um zusätzliche Leerzeichen aus der letzten Zeichenfolge zu entfernen. – iDev

+0

Ich habe bereits versucht 'completeTrimmed = [completeTrimmed stringByReplacingOccurrencesOfString: @„‚withString: @‘ ‚];', aber es tut nichts – Mahir

+0

@‘“ sollte etwa 15 Räume dazwischen, haben aber den Kommentar autocorrects es 1 Leerzeichen – Mahir

Antwort

1

Ich habe mit der Frage oben versucht, und das ist, wie ich es fest,

NSString *retString = [[result stringByDecodingHTMLEntities] retain]; 
[result release]; 

retString = [retString stripDuplicateCharactersInSet:[NSCharacterSet whitespaceCharacterSet] withString:@" "]; 
retString = [retString stripDuplicateCharactersInSet:[NSCharacterSet newlineCharacterSet] withString:@"\n"]; 

ich als eine Kategorie-Methode auf NSString definiert haben,

- (NSString *)stripDuplicateCharactersInSet:(NSCharacterSet *)characterSet withString:(NSString *)joiningString; 

Die Umsetzung wird wie folgt,

Fügen Sie die obige Methode in NSString+HTML.m Datei als eine Kategorie aufhinzu. Im Wesentlichen in dem HTML, das von Ihnen gegeben wurde, wurden Leerzeichen und Zeilenumbruch mehrfach gemischt, und der Versuch, Zeilenumbruch allein zu entfernen, funktionierte nicht. Daher entferne ich doppelte Zeilenumbrüche und Leerräume, wie oben gezeigt, indem ich vergleiche, ob der String nach dem Entfernen eine neue Zeile oder Leerzeichen hat und dann an die Hauptsaite angehängt wird.

Alternativ können Sie auch als versuchen,

NSString *retString = [[result stringByDecodingHTMLEntities] retain]; 
[result release]; 

retString = [retString stripDuplicateNewlineCharacters]; 

Verfahren wie definiert ist,

- (NSString *)stripDuplicateNewlineCharacters { 

    NSMutableString *originalStr = [NSMutableString string]; 

    if (!self) { 
     return nil; 
    } 

    NSArray *componentsArray = [self componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]; 

    int counter = 0; 
    for (NSString *stringComponent in componentsArray) { 

     counter ++; 

     stringComponent = [stringComponent stringByReplacingOccurrencesOfString:@" " withString:@"<#$%$#>"]; 
     stringComponent = [stringComponent stringByReplacingOccurrencesOfString:@"<#$%$#><#$%$#>" withString:@"<#$%$#>"]; 
     stringComponent = [stringComponent stringByReplacingOccurrencesOfString:@"<#$%$#>" withString:@" "]; 

     if ((stringComponent) && ([stringComponent length] > 0) && (![stringComponent isEqualToString:@" "]) && (![stringComponent isEqualToString:@"\n"])) { 

      if ([componentsArray count] == counter) { 
       [originalStr appendFormat:@"%@", stringComponent]; 
      } else { 
       [originalStr appendFormat:@"%@\n", stringComponent]; 
      } 
     } 
    } 

    return originalStr; 
} 

In diesem Fall werden die doppelten weißen Flächen sind in der Methode selbst entfernt, während neue Linie zu entfernen Figuren.

+0

Jetzt ist es ein langer Absatz. Ich habe versucht, die Methode 'stripDuplicateCharacters' für Whitespaces zu entfernen, so dass nur die Newline-Methode übrig bleibt. Das Ergebnis ist eine zusätzliche Leerzeile nach Absatz 1, richtiger Abstand nach Absatz 2 und für die restlichen Absätze beginnen die Absätze auf einer neuen Zeile. Zwischen den Absätzen ist jedoch kein Platz. – Mahir

+0

Ich habe die Methode für das Newline-Zeichenset bearbeitet, und jetzt sind alle Absätze in Ordnung, außer 1, die eine zusätzliche Zeile Leerzeichen enthält. Ich habe die Bedingung '(! [StringComponent isEqualToString: @" "]) entfernt.' – Mahir

+0

@Mahir, Das ist seltsam, weil es für mich gut funktioniert. Können Sie diese 'retString = [retString stringByReplacingOccurrencesOfString: @ "\ n" withString: @ "** # NEWLINE # **"] Versuchen Sie,' vor dem Drucken, wie viele Zeilenumbrüche gibt es zwischen den Absätzen zu trösten und sehen? – iDev

4

prüfen mit diesem,

//Decode HTML entities and return 
    NSString *retString = [result stringByDecodingHTMLEntities]; 
    [result release]; 

    //Drain 
    [pool drain]; 

    retString = [[retString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] retain]; 

    //Return 
    return [retString autorelease]; 
} 

Wenn die oben nicht funktioniert, auch versuchen, mit

completeTrimmed = [completeTrimmed stringByReplacingOccurrencesOfString:@"\n" withString:@""]; 

und

+0

noch nichts ... – Mahir

+0

Falls es hilft, kommt der Quellcode von Artikeln wie diese http://www.laloyolan.com/news/after-defeat-cloudy-future-ahead-for-mitt-romney/article_63f50e24- 294e-11E2-a963-001a4bcf6878.html – Mahir

+0

ich benutze die Körperabschnitte – Mahir

2

Sie könnten @ "/ n/n" durch @ "/ n" ersetzen, um die Anzahl der Zeilenumbrüche zu reduzieren.

+0

Ich habe versucht, 'stringByReplacingString: @„/ n/n“mit: @„/ n“' aber nichts geändert – Mahir

+0

ich, dass es realisiert hat nicht funktioniert, weil die aufeinanderfolgenden/n Zeichen durch ein Leerzeichen getrennt wurden – Mahir

+0

Glad gefunden, das Problem . Sie können also "/ n/n" durch "/ n" ersetzen – Darren

Verwandte Themen