У меня есть строка 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);