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)]);
Amal T S
  • 3,327
  • 2
  • 24
  • 57

6 Answers6

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)]);
rckoenes
  • 69,092
  • 8
  • 134
  • 166
  • Yes you are right, if could use some error checking. – rckoenes Dec 19 '14 at 14:05
  • 1
    Good answer. By the way, renaming `end` as `length` might add clarity for future readers. – jlehr Dec 19 '14 at 15:28
  • 2
    @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. – Ben Kane Dec 19 '14 at 19:12
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

Amal T S
  • 3,327
  • 2
  • 24
  • 57
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]);
ArtFeel
  • 11,701
  • 4
  • 29
  • 41
1
 NSString *serverOutput = @"<id>100</id>";
serverOutput = [serverOutput stringByReplacingOccurrencesOfString:@"<id>" withString:@""];
serverOutput = [serverOutput stringByReplacingOccurrencesOfString:@"</id>" withString:@""];

NSLog(@"%@",serverOutput);
Jack Patoliya
  • 507
  • 6
  • 14
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]);
}
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.

Ben Kane
  • 9,331
  • 6
  • 36
  • 58