我正在从google weather 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
问题在于它解析所有标签,直到达到“城市数据”,因为在巴黎,法兰西岛的名称中有一个非ascii字符然后它就停止了。之后它不像postal_code那样处理标签。纬度,经度等。
所以我的问题是,有没有办法可以从返回的URL XML字符串中删除所有非ascii字符?
答案 0 :(得分:8)
我知道会发生什么,我只是遇到同样的问题......
在解析器中查看您的foundCharacters
方法......
我有这样的事情:
if (!currentElementValue) {
currentElementValue = [[NSMutableString alloc] initWithString:string];
}
和currentElementValue
在特殊字符发生时就停止了。
现在我的工作代码是:
if (!currentElementValue) {
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue appendString:string];
}
请务必在currentElementValue
方法结束时将nil
设为didEndElement
答案 1 :(得分: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
答案 2 :(得分: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
标头应该可以解决问题,但这会使检索数据变得更复杂。
答案 3 :(得分:-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;
}