Найдите число узлов в NSString и добавьте подчеркивание перед ним, чтобы исправить недопустимый XML - PullRequest
1 голос
/ 24 января 2012

У меня есть строка XML, которая мне возвращается, иногда она недопустима, используя числа в качестве имен узлов, таких как: <2>. Я хотел бы отсканировать весь мой NSString, содержащий XML, и найти следующее:

<numeric value // e.g. <1  or <2

</numeric value // e.g. </1 or </2

Затем я хотел бы поставить подчеркивание перед числом, чтобы оно изменило недействительное значение на XML, как показано ниже:

<_2>
</_2>

Мне интересно, NSScanner справится с этой задачей, но я не уверен, как решить эту проблему. Прямо сейчас я просто использую stringByReplacingOccurrencesOfString:withString:, но мне приходится жестко кодировать числовые значения для замены, что я не считаю хорошей идеей.

UPDATE:

Я попробовал и использовал NSRange. Вот что я придумал. Он работает примерно на 95%, но в больших XML-строках он пропускает несколько последних тегов </ >, не знаю почему. Любые комментарии или помощь по улучшению этого?

// Changeable string
NSMutableString *editable = [[[NSMutableString alloc] initWithString:str] autorelease];

// Number Formatter
NSLocale *l_en = [[[NSLocale alloc] initWithLocaleIdentifier: @"en_US"] autorelease];
NSNumberFormatter *f = [[[NSNumberFormatter alloc] init] autorelease];
[f setLocale: l_en];

// Make our first loop
NSUInteger count = 0, length = [str length];
NSRange range = NSMakeRange(0, length); 
while(range.location != NSNotFound) {

    // Find first character
    range = [str rangeOfString: @"<" options:0 range:range];

    // Make sure we have not gone too far
    if (range.location+1 <= length) {

        // Check the digit after this
        NSString *after = [NSString stringWithFormat:@"%c", [str characterAtIndex:range.location+1]];

        // Check if we return the number or not
        if ([f numberFromString:after]) {

            // Update the string
            [editable insertString:@"_" atIndex:(range.location+1)+count];
            count++;

        }//end

    }//end

    // Check our range
    if(range.location != NSNotFound) {
        range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
    }//end

}//end

// Our second part
NSUInteger slashLength = [editable length];
NSRange slashRange = NSMakeRange(0, slashLength); 
while(slashRange.location != NSNotFound) {

    // Find first character
    slashRange = [editable rangeOfString: @"</" options:0 range:slashRange];

    // Make sure we have not gone too far
    if (slashRange.location+2 <= slashLength) {

        // Check the digit after this
        NSString *afterSlash = [NSString stringWithFormat:@"%c", [editable characterAtIndex:slashRange.location+2]];

        // Check if we return the number or not
        if ([f numberFromString:afterSlash]) {

            // Update the string
            [editable insertString:@"_" atIndex:(slashRange.location+2)];

        }//end

    }//end

    // Check our range
    if(slashRange.location != NSNotFound) {
        slashRange = NSMakeRange(slashRange.location + slashRange.length, slashLength - ((slashRange.location+2) + slashRange.length));
    }//end

}//end

NSLog(@"%@", editable);

1 Ответ

0 голосов
/ 16 февраля 2012

В итоге я нашел решение.Вот метод, который я использовал:

- (NSString *)insertUnderscoreInString:(NSString *)fullString afterString:(NSString *)afterString {

    // Changeable string
    NSMutableString *editable = [[[NSMutableString alloc] initWithString:fullString] autorelease];

    // Number Formatter
    NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: @"en_US"];
    NSNumberFormatter *f = [[[NSNumberFormatter alloc] init] autorelease];
    [f setLocale: l_en];
    [l_en release];

    // Make our loop
    NSUInteger count = 0, length = [fullString length];
    NSRange range = NSMakeRange(0, length); 
    while(range.location != NSNotFound) {

        // Find first character
        range = [fullString rangeOfString:afterString options:0 range:range];

        // Make sure we have not gone too far
        if (range.location+1 <= length) {

            // Check the digit after this
            NSString *after = [NSString stringWithFormat:@"%c", [fullString characterAtIndex:range.location+afterString.length]];

            // Check if we return the number or not
            if ([f numberFromString:after]) {

                // Update the string
                [editable insertString:@"_" atIndex:(range.location+afterString.length)+count];
                count++;

            }//end

        }//end

        // Check our range
        if(range.location != NSNotFound) {
            range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
        }//end

    }//end

    return editable;

}//end

Итак, вы можете проверить его, используя:

NSString *val = [self insertUnderscoreInString:str afterString:@"<"];
NSString *val2 = [self insertUnderscoreInString:val afterString:@"</"];
NSLog(@"%@", val2);
...