在 NSString 中查找数字节点并在其前面添加下划线以修复无效的 XML

发布于 2024-12-29 00:14:05 字数 2880 浏览 1 评论 0原文

我有一个返回给我的 XML 字符串,有时使用数字作为节点名称是无效的,例如:<2>。我想扫描保存 XML 的整个 NSString ,并搜索以下内容:

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

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

然后我想在数字前放置一个下划线,以便它将无效的更改为有效的 XML,如下所示:

<_2>
</_2>

我想知道 NSScanner 是否可以完成这项工作,但我不确定如何解决这个问题。现在我只是使用 stringByReplacingOccurrencesOfString:withString: ,但我必须在要替换的数值中进行硬编码,我认为这不是一个好主意。

更新:

我尝试了一下并使用了 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);

I have an XML string that gets returned to me, sometimes it is invalid using numbers as node names such as: <2>. I would like to scan my entire NSString which holds the XML, and search for the following:

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

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

I would then like to place an underscore before the number, so that it will change the invalid, to valid XML, like the following:

<_2>
</_2>

I am wondering is NSScanner would do the job, but I am unsure how to attack this problem. Right now I am just using stringByReplacingOccurrencesOfString:withString: but I am having to hardcode in the number values to replace, which I don't think is a good idea.

UPDATE:

I gave it a try and used NSRange. Here is what I came up with. It is working about 95%, but on large xml strings it misses the last few </ > tags, not sure why. Any comments or help on improving this?

// 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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

仅此而已 2025-01-05 00:14:05

我最终找到了一个解决方案。这是我使用的方法:

- (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);

I ended up figuring out a solution. Here is the method that I used:

- (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

So, then you could test it using:

NSString *val = [self insertUnderscoreInString:str afterString:@"<"];
NSString *val2 = [self insertUnderscoreInString:val afterString:@"</"];
NSLog(@"%@", val2);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文