2

我正在从谷歌天气 api 读取 XML 文件并使用 NSXMLParser 解析它。有问题的城市是巴黎。这是我得到的一个简短的 xml 输出

           <?xml version="1.0"?>
    <xml_api_reply version="1">
    <weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" ><forecast_information>
    <city data="Paris, Île-de-France"/>
    <postal_code data="Paris"/>
    <latitude_e6 data=""/>
    <longitude_e6 data=""/> 
...
...

现在我用来解析这个xml的代码是

NSString *address = @"http://www.google.com/ig/api?weather=Paris";
    NSURL *URL = [NSURL URLWithString:address];

NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];
    [parser setDelegate:self];
    [parser parse];
...

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict 
{

    NSLog(@"XML Parser 1 ... elementName ... %@", elementName);

}

这是我为上述 xml 获得的输出

XML Parser 1 ... elementName ... xml_api_reply
XML Parser 1 ... elementName ... weather
XML Parser 1 ... elementName ... forecast_information

问题是它解析所有标签直到它到达“城市数据”,因为名称 Paris, Île-de-France 中有一个非 ascii 字符,然后它就停止了。之后它不会像 postal_code 那样处理标签。纬度、经度等

所以我的问题是,有没有办法可以从返回的 URL XML 字符串中删除所有非 ascii 字符?

4

4 回答 4

8

我知道会发生什么,我只是遇到了同样的问题......

foundCharacters在解析器中查看您的方法...

我有这样的事情:

if (!currentElementValue) {
   currentElementValue = [[NSMutableString alloc] initWithString:string];
}

当特殊字符发生时currentElementValue就停止了。

现在我的工作代码是:

if (!currentElementValue) {
    currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
    [currentElementValue appendString:string];
}

请记住在方法结束时设置currentElementValuenildidEndElement

于 2012-11-01T18:25:30.920 回答
2

行。我已经解决了这个问题。这就是我让它工作的方式。

首先我要做的是从带有特殊字符的 URL 中获取 XML。然后我从 XML 字符串中删除所有特殊字符。然后我将字符串转换为 NSdata,然后将该 nsdata 对象传递给我的 NSXMLParser。因为它没有更多的特殊字符 NSXMLParser 很高兴。

这是将来可能遇到的任何人的代码。非常感谢所有为这篇文章做出贡献的人!

NSString *address = @"http://www.google.com/ig/api?weather=Paris";
    NSURL *URL = [NSURL URLWithString:address];
    NSError *error;    
    NSString *XML = [NSString stringWithContentsOfURL:URL encoding:NSASCIIStringEncoding error:&error];

    //REMOVE ALL NON-ASCII CHARACTERS
         NSMutableString *asciiCharacters = [NSMutableString string];
         for (NSInteger i = 32; i < 127; i++)  
         {
         [asciiCharacters appendFormat:@"%c", i];
         }

         NSCharacterSet *nonAsciiCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:asciiCharacters] invertedSet];

         XML = [[XML componentsSeparatedByCharactersInSet:nonAsciiCharacterSet] componentsJoinedByString:@""];

    NSData *data = [XML dataUsingEncoding:NSUTF8StringEncoding];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    [parser setDelegate:self];
    [parser parse];

编辑:

NSXMLParser 是一个可怕的工具。我已在所有应用程序中成功使用 RaptureXML。它超级易于使用,并且避免了所有这些无意义的非 ascii 字符。https://github.com/ZaBlanc/RaptureXML

于 2012-08-06T17:53:47.567 回答
0

您遇到的问题是 Google 的响应使用的编码与您期望的 ASCII 或 UTF8 不同。使用方便的命令行工具curl,很容易看出:

$ curl -I http://www.google.com/ig/api?weather=Paris
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
Content-Type: text/xml; charset=ISO-8859-1
...

如果您查找 ISO-8859-1,您会发现它也被称为 Latin-1 字符集。内置编码选项之一是NSISOLatin1StringEncoding,因此请执行以下操作:

NSString *XML = [NSString stringWithContentsOfURL:URL encoding:NSISOLatin1StringEncoding error:&error];

使用正确的编码将使 NSString 能够弄清楚如何解释字符,并且您将获得可用的数据。或者,您可以修改您的请求以指定您希望 Google 提供的字符编码。这可能更可取,这样您就不必尝试将您使用的编码与特定请求相匹配。

编辑:到目前为止,我的答案集中在将响应作为可读字符串获取。不过,我看到您的真正问题涉及使用 NSXMLParser 进行解析。我认为您在这里至少有两个选择:

  • 修改您收到的 XML 以包含字符编码。您返回的 XML 是 Latin-1 编码的,但 XML 标记只显示:<?xml version="1.0"?>。您可以将其修改为:<?xml version="1.0" encoding="ISO-8859-1"?>. 我不知道这是否会解决 NSXMLParser 的问题,但它可能会。

  • 如上所述,向Google请求您想要的字符集。向请求添加Accept-Charset标头应该可以解决问题,尽管这会使检索数据变得更加复杂。

于 2012-08-06T17:11:58.933 回答
-2

坚持使用 ISO-8859-1,因此您不需要“删除特殊字符”。使用不同的机制来获取 http 数据。

使用 NSURLConnection,从长远来看,它更加灵活和异步。

NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                            cachePolicy:NSURLRequestUseProtocolCachePolicy
                                        timeoutInterval:15.0];

 NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
    if (theConnection) {
        // Create the NSMutableData to hold the received data.
        // receivedData is an instance variable declared elsewhere.
        receivedData = [[NSMutableData data] init];
        return YES;
    } else {
        // Inform the user that the connection failed.
        return NO;
    }
}

#pragma mark - Url connection data delegate

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [receivedData setLength:0];
}


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    receivedData = nil;
    [self badLoad];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    //inform delegate of completion
    [self.delegate fetchedData:receivedData];

    receivedData = nil;
}
于 2012-08-06T16:52:49.953 回答