2012-08-06 83 views
2

我正在从谷歌天气api中读取XML文件并使用NSXMLParser解析它。有问题的城市是巴黎。下面是一个简单的XML输出我得到NSXMLParser在遇到特殊字符后停止解析

  <?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 

的问题在于它解析了所有标签,直到达到“城市数据”为止,因为在法国巴黎Île-de-France有一个非ascii字符,然后它就停止。它不像postal_code那样处理标签。纬度,经度等

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

+0

结束设置currentElementValuenil,此对象不会对你做任何事情:'的NSString * XML = [NSString的stringWithContentsOfURL :URL编码:NSASCIIStringEncoding error:&error];'你根本没有使用它。 'NSXMLParser'直接从'URL'加载。 – 2012-08-06 16:54:52

+0

您是否收到解析或验证错误? – 2012-08-06 16:56:23

+0

@Justin - 你正确的操纵XML字符串不会做任何事情,因为我将URL传递给XML解析器。有没有一种方法可以在 - (void)分析器中修改该xml的结果?若要:杰西 - 我没有得到任何错误,会发生什么是XML停止分析后,它击中第一个特殊字符。我有更多的标签,但没有阅读 – 2012-08-06 17:14:10

回答

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

+1

如果您需要特殊字符怎么办? – Steven 2013-03-07 18:09:07

-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; 
} 
+0

但是,一旦收到数据,您仍然必须将其解释为文本,这意味着您必须使用正确的编码。所返回的数据不是UTF8,因此试图以这种方式解释它是不正确的。你关于使用NSURLConnection来避免阻塞的观点很好,但是OP可能会在后台线程上发出这个请求,因为同步调用并不是一件坏事,而且对于单线请求。 – Caleb 2012-08-06 17:14:47

+0

与实际问题无关 – Rakesh 2014-05-30 06:00:44

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头应该能够做到这一点,尽管这会使得检索数据变得更加复杂一些。

+0

谢谢Caleb - 我改变了一下我的问题。问题在这里。 NSXMLParser * parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];和 - (void)解析器:...我如何修复返回的URL结果中的特殊字符? – 2012-08-06 17:19:04

+0

正确 - 请参阅我对该主题的一些想法的编辑。 – Caleb 2012-08-06 17:31:44

8

我知道可能会发生,我只是有同样的问题...

看看你的解析器您foundCharacters方法...

我有这样的事情:

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

currentElementValue刚刚停止时发生特殊字符。

现在我的工作代码为:

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

记住你didEndElement方法

+0

什么是“currentElementValue” – ram880 2015-06-19 10:59:12