NSXMLParser“foundCharacters”委托方法未调用

时间:2014-02-14 16:06:27

标签: ios objective-c xml google-maps nsxmlparser

我在解析XML方面遇到了问题,因此我使用NSLogs查看了我的代码并注意到了 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 没被叫。

我的XML:

<?xml version="1.0"?>
<locations>
<location>
<name>Americas</name>
<address></address>
<gid>CoQBdAAAAE2tdzw4RGvnvaUZTk6N1ByNtosmD--ZYfcmkkPkR6R6v_nN9gJCO1INOVg-S5rzy7BATEUmvAQzh8hClafZbph2wSgfD28gXNJAttXLUbqzQMaql3rVbisSUv2a2r_H6ktOSaI5lLvf0GNthT5jn2JfAdD_HfUls6qhMvrm5e5XEhDcF5uRjlfpSqI_aciS_QPaGhQVVHenbOKZBQMSoCzsoIsdfw313Q</gid>
<type>
<1>political</1><2/><3/><4/><5/>
</type>
<phone></phone>
<rating></rating>
<icon>http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png</icon>
<website></website>
<longitude>-105.2551187</longitude>
<latitude>54.5259614</latitude>
</location>
</locations>

我的实施的相关部分

- (void)viewDidLoad
{
    [super viewDidLoad];
...
    if(!self.distance){self.distance = @"250000";}
    NSString *string = [NSString stringWithFormat:@"http://fishbe.in/lab/reserverr/api/?term=%@&lat=%f&long=%f&limit=100&distance=%@", self.searchterm, location.coordinate.latitude, location.coordinate.longitude, self.distance];
    NSLog(@"%@", string);
    NSURL *URL = [NSURL URLWithString:string];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];

    [parser setDelegate:self];
    [parser setShouldResolveExternalEntities:NO];
    [parser setShouldProcessNamespaces:NO];
    [parser setShouldReportNamespacePrefixes:NO];
    [parser parse];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    self.element = elementName;
    if ([self.element isEqualToString:@"locations"]) {
        self.items    = [[NSMutableArray alloc] init];
    }

}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    NSLog(@"HI"); //Not outputted
    if ([self.element isEqualToString:@"name"]) {
        self.result = [[ReserverrSearchResult alloc] init];
        [self.result setTitle:string];
        NSLog(@"%@", string);
    } else if ([self.element isEqualToString:@"address"]) {
        [self.result setVicinity:string];
        NSLog(@"%@", string);
    } else if ([self.element isEqualToString:@"gid"]) {
        [self.result setGid:string];
        NSLog(@"%@", string);
    } else if ([self.element isEqualToString:@"latitude"]) {
        [self.result setLatitude:[string floatValue]];
        NSLog(@"%@", string);
    } else if ([self.element isEqualToString:@"longitude"]) {
        [self.result setLongitude:[string floatValue]];
        NSLog(@"%@", string);
    }

}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    if ([elementName isEqualToString:@"location"]) {
        [self.items addObject:self.result];

    }

}

- (void)parserDidEndDocument:(NSXMLParser *)parser {

    [self addAnnotations];

}

编辑 - 添加

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
    NSLog(@"%@",parseError);
}

一无所获。

1 个答案:

答案 0 :(得分:1)

有几个问题:

  1. 正如wain指出的那样,你应该实施parser:parseErrorOccurred:,它会告诉你什么是错的。

  2. 如果searchterm包含任何为网址保留字符的字符(例如空格,加号,符号等),我会发现问题。你应该总是百分之百地逃避我认为是用户提供的搜索词并将其添加到URL:

    NSString *string = [NSString stringWithFormat:@"http://fishbe.in/lab/reserverr/api/?term=%@&lat=%f&long=%f&limit=100&distance=%@", [self percentEscapeString:self.searchterm], location.coordinate.latitude, location.coordinate.longitude, self.distance];
    

    您可以使用以下方法:

    - (NSString *)percentEscapeString:(NSString *)string
    { 
        NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                     (CFStringRef)string,
                                                                                     (CFStringRef)@" ",
                                                                                     (CFStringRef)@":/?@!$&'()*+,;=",
                                                                                     kCFStringEncodingUTF8));
        return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    }
    

    注意,不要依赖stringByAddingPercentEscapesUsingEncoding来执行百分比转义。你真的想使用CFURLCreateStringByAddingPercentEscapes,就像上面一样。

  3. 另外,您的XML格式不正确。我不相信NSXMLParser会接受数字的元素名称。所以,而不是:

    <type>
        <1>political</1><2/><3/><4/><5/>
    </type>
    

    你可能想要:

    <types>
        <type>political</type>
        <type></type>
        <type></type>
        <type></type>
        <type></type>
    </types>
    

    或者,如果您确实需要这些数字标识符:

    <types>
        <type id="1">political</type>
        <type id="2"></type>
        <type id="3"></type>
        <type id="4"></type>
        <type id="5"></type>
    </types>
    

    在后一个示例中,您的didStartElement可以使用attributeDict提取id标识符。

  4. 您报告parseErrorOccurred没有返回任何内容。这意味着您的服务器可能没有返回任何内容。这可能是由许多问题引起的。尝试使用您的URL并返回数据(例如,返回NSStringNSData,而不是解析器),看看响应的样子。例如,出于测试目的,您可以这样做:

    NSError  *error;
    NSData   *data    = [NSData dataWithContentsOfURL:url options:0 error:&error];
    NSString *results = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    // confirm error is `nil` and `results` is well-formed XML;
    // you can then pass the `data` to `NSXMLParser` with `initWithData` if you want
    

    我敢打赌它是空的(对于某些搜索术语而言,可能是因为缺少百分比逃逸,或者来自无数服务器问题)。

  5. 这可能不是问题,但值得注意的是,在foundCharacters中保存结果在概念上存在风险,因为有时在didStartElementdidEndElement之间,你会有多次调用foundCharacters来检索数据。通常,人们会在NSMutableString中实例化didStartElement,在foundCharacters中附加到didEndElement,然后将其保存在{{1}}中。