使用NSRegularExpression提取两个XML标签之间的文本

8
如何使用NSRegularExpression提取“badgeCount”标签之间的值“6”。以下是服务器的响应:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><badgeCount>6</badgeCount><rank>2</rank><screenName>myName</screenName>

以下是我尝试过的代码,但没有成功。实际上它会进入else部分并打印“regex的值为nil”:
NSString *responseString =   [[NSString alloc] initWithBytes:[responseDataForCrntUser bytes] length:responseDataForCrntUser.length encoding:NSUTF8StringEncoding];

NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?<=badgeCount>)(?:[^])*?(?=</badgeCount)" options:0 error:&error];
if (regex != nil) {
    NSTextCheckingResult *firstMatch = [regex firstMatchInString:responseString options:0 range:NSMakeRange(0, [responseString length])];
    NSLog(@"NOT NIL");
    if (firstMatch) {
        NSRange accessTokenRange = [firstMatch rangeAtIndex:1];
        NSString *value = [urlString substringWithRange:accessTokenRange];
        NSLog(@"Value: %@", value);
    }
}
else
    NSLog(@"Value of regex is nil");

如果你能提供示例代码,那将不胜感激。

注意:我不想使用NSXMLParser。


为什么你不想使用XML解析器来解析XML? - Mat
你到目前为止尝试了什么? - Mat
提取仅几个值时不需要使用NSXMLParser...我已经使用http://gskinner.com/RegExr/在线工具获得了所需的正则表达式"(?<=badgeCount>)(?:[^])*?(?=</badgeCount)",但无法在NSRegularExpression中使用相同的表达式... - Prazi
编辑你的问题,包含你尝试过的代码,清楚地解释它的不正常工作之处。 - Mat
2个回答

18

例子:

NSString *xml = @"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><badgeCount>6</badgeCount><rank>2</rank><screenName>myName</screenName>";
NSString *pattern = @"<badgeCount>(\\d+)</badgeCount>";

NSRegularExpression *regex = [NSRegularExpression
                                      regularExpressionWithPattern:pattern
                                      options:NSRegularExpressionCaseInsensitive
                                      error:nil];
NSTextCheckingResult *textCheckingResult = [regex firstMatchInString:xml options:0 range:NSMakeRange(0, xml.length)];

NSRange matchRange = [textCheckingResult rangeAtIndex:1];
NSString *match = [xml substringWithRange:matchRange];
NSLog(@"Found string '%@'", match);

NSLog输出:

Found string '6'

如果我想要获取标签<screenName>之间的值"myName",我需要创建新的正则表达式还是可以在同一个正则表达式中完成。 - Prazi
1
需要一个新的正则表达式,因为"\d+"指定了一个或多个数字。对于名称,您将需要类似于"\S+"的内容(如果名称中没有空格)。有一个更通用的正则表达式,在任何情况下都应该有效:@"<badgeCount>([^<]+)</badgeCount>",它表示任何东西直到"<"字符。 - zaph
感谢您的所有帮助,非常感激。这意味着我需要两个单独的模式:1. <badgeCount>([^<]+)</ badgeCount> 用于获取徽章计数 2. <screenName>([^<]+)</ screenName> 用于获取屏幕名称。 - Prazi
是的,因为周围的文本不同。 - zaph

5

在Swift 3.0中进行操作

func getMatchingValueFrom(strXML:String, tag:String) -> String {
    let pattern : String = "<"+tag+">(.*?)</"+tag+">" // original didn't work: "<"+tag+">(\\d+)</"+tag+">"
    let regexOptions = NSRegularExpression.Options.caseInsensitive
    
    do {
        let regex = try NSRegularExpression(pattern: pattern, options: regexOptions)
        let textCheckingResult : NSTextCheckingResult = regex.firstMatch(in: strXML, options: NSRegularExpression.MatchingOptions(rawValue: UInt(0)), range: NSMakeRange(0, strXML.count))!
        let matchRange : NSRange = textCheckingResult.range(at: 1)
        let match : String = (strXML as NSString).substring(with: matchRange)
        return match
    } catch {
        print(pattern + "<-- not found in string -->" + strXML )
        return ""
    }
}

附注:这是对@zaph在Objective-C中提供的解决方案的相应Swift解决方案。


2
"<"+tag+">(\\d+)</"+tag+">" 对我不起作用,我不得不使用 "<"+tag+">(.*?)</"+tag+">" - Alejandro Cotilla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接