遇到特殊字符后,NSXMLParser停止parsing

我正在从谷歌天气api读取一个XML文件,并使用NSXMLParserparsing它。 有问题的城市是巴黎。 这里是我得到一个简单的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 

问题是,它parsing所有的标签,直到它达到“城市数据”,因为在巴黎,法兰西岛这个名字中有一个非ascii字符,然后它只是停止。 它不像postal_code那样处理标签。 纬度,经度等

所以我的问题是,有没有办法从返回的URL XMLstring中删除所有非ASCII字符?

我知道会发生什么,我也有同样的问题…

在parsing器中查看您的foundCharacters方法…

我有这样的事情:

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

currentElementValue刚刚停止获取特殊字符发生。

现在我的工作代码是:

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

请记住在didEndElement方法的末尾将currentElementValue设置为nil

好。 我已经解决了这个问题。 这是我得到它的工作。

首先我要从特殊字符的URL中获取XML。 然后我从XMLstring中去掉所有的特殊字符。 然后我将该string转换为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

您遇到的问题是,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提供的字符编码。 这可能是可取的,所以你不必尝试匹配你使用的编码到一个特定的请求。

编辑:到目前为止,我的答案集中在刚刚得到响应作为一个可读的string。 不过,我发现你真正的问题涉及使用NSXMLParserparsing。 我认为你在这里至less有两个select:

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

  • 如上所示, 请求 Google 提供的字符集 。 将Accept-Charset头添加到请求中应该有所诀窍,尽pipe这会使得检索数据变得更复杂一些。

坚持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; }