1

How can I get a string between 2 known strings? For example:

<id> 100 </id>

I want to get the 100 from this string.

I have try this code but it doesn´t work. The NSLog is:

<id>100

Code:

NSString *serverOutput = @"<id>100</id>";
NSRange start = [serverOutput rangeOfString:@"<id>"];
NSRange end = [serverOutput rangeOfString:@"</id>"];
NSLog(@"%@",[serverOutput substringWithRange:NSMakeRange(start.location, end.location)]);
2
  • If it is Xml why not use an XML parser? Commented Dec 19, 2014 at 13:37
  • No.Its only a example :D Commented Dec 19, 2014 at 13:39

6 Answers 6

8

You where nearly there, but the range location is the start of the not the end. So you have to add the length of the range.

Since the you moved the start of you string, you need to short the length with the offset:

NSString *serverOutput = @"<id>100</id>";
NSRange startRange = [serverOutput rangeOfString:@"<id>"];
NSRange endRange = [serverOutput rangeOfString:@"</id>"];

NSInteger start = NSMaxRange (startRange);
NSInteger length = endRange.location - startRange.length;

NSLog(@"%@", [serverOutput substringWithRange:NSMakeRange(start, length)]);
Sign up to request clarification or add additional context in comments.

3 Comments

Yes you are right, if could use some error checking.
Good answer. By the way, renaming end as length might add clarity for future readers.
@rckoenes I think NSMaxRange(startRange) would be preferred over startRange.location + startRange.length. No reason to do the math yourself when a function already exists to do it for you.
4

In Swift:

extension String {

    func slice(from: String, to: String) -> String? {

        return (range(of: from)?.upperBound).flatMap { substringFrom in
            (range(of: to, range: substringFrom..<endIndex)?.lowerBound).map { substringTo in
                String(self[substringFrom..<substringTo])
            }
        }
    }
}

Input

let serverOutput = "<id>100</id>"
let resultString = serverOutput.slice(from: "<id>", to: "</id>")
print(resultString)

Output

100

Comments

1

This is how NSRange defined:

typedef struct _NSRange {
    NSUInteger location;
    NSUInteger length;
} NSRange;

So, if you want to get 100, you should substring like this:

NSRange substringRange = NSMakeRange(start.location + start.length, end.location - start.length);
NSLog(@"%@", [serverOutput substringWithRange:substringRange]);

Comments

1
 NSString *serverOutput = @"<id>100</id>";
serverOutput = [serverOutput stringByReplacingOccurrencesOfString:@"<id>" withString:@""];
serverOutput = [serverOutput stringByReplacingOccurrencesOfString:@"</id>" withString:@""];

NSLog(@"%@",serverOutput);

Comments

1

I think that you should use a regular expression.

NSString *serverOutput = @"<id>100</id>";
NSString *pattern = @"<id>([0-9]+)</id>";
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                       options:NSRegularExpressionCaseInsensitive
                                                                         error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:serverOutput
                                                options:NSMatchingReportProgress
                                                  range:NSMakeRange(0, serverOutput.length)];
if (!error && match && match.numberOfRanges >= 2) {
    NSRange range = [match rangeAtIndex:1];
    NSLog(@"%@", [serverOutput substringWithRange:range]);
}

Comments

0

You want to start at the end of the first string, so you just need to change:

NSLog(@"%@",[serverOutput substringWithRange:NSMakeRange(start.location, end.location)]);

To:

NSLog(@"%@",[serverOutput substringWithRange:NSMakeRange(NSMaxRange(start), end.location - start.length)]);

Notice that I also subtracted the length of the start string because we just offset by that much.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.