Iphone NSXMLParser遇到特殊字符后停止解析
我正在从google weather api读取一个XML文件,并使用NSXMLParser对其进行解析。讨论中的城市是巴黎。下面是我得到的一个简短的xml输出Iphone NSXMLParser遇到特殊字符后停止解析,iphone,ios,xml,xcode,xcode4,Iphone,Ios,Xml,Xcode,Xcode4,我正在从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
<?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获得的输出
XML Parser 1 ... elementName ... xml_api_reply
XML Parser 1 ... elementName ... weather
XML Parser 1 ... elementName ... forecast_information
问题是,它解析所有标记,直到到达“城市数据”,因为巴黎,法国巴黎的名称中有一个非ascii字符,然后它就停止了。它不会像邮政编码那样处理标签。纬度、经度等
所以我的问题是,有没有办法从返回的URL XML字符串中删除所有非ascii字符?坚持使用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;
}
你所遇到的问题是,谷歌的回应使用了与你所期望的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,你会发现它也被称为拉丁字符集。内置编码选项之一是nsisolatin1stringecoding
,因此请执行以下操作:
NSString *XML = [NSString stringWithContentsOfURL:URL encoding:NSISOLatin1StringEncoding error:&error];
使用正确的编码将使NSString能够理解如何解释字符,并且您将获得可用的数据。或者,您可以修改请求以指定希望Google提供的字符编码。这可能更可取,这样您就不必尝试将您使用的编码与特定请求相匹配
Edit:到目前为止,我的答案主要是将响应作为可读字符串。不过,我发现您真正的问题是使用NSXMLParser进行解析。我认为你至少有两个选择:
- 修改收到的XML,以包含字符编码。返回的XML是拉丁文1编码的,但XML标记只显示:
。您可以将其修改为:
。我不知道这是否能解决NSXMLParser的问题,但它可能会 - 如上所述,从谷歌请求您想要的字符集。将
头添加到请求中应该可以做到这一点,不过这会使检索数据变得更复杂一些Accept字符集
- 好的。我已经解决了这个问题。我就是这样让它工作的
首先,我要做的是从带有特殊字符的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];
NSString*地址=@”http://www.google.com/ig/api?weather=Paris";
NSURL*URL=[NSURL URLWithString:address];
n错误*错误;
NSString*XML=[NSString stringWithContentsOfURL:URL编码:NSASCIIStringEncoding错误:&错误];
//删除所有非ASCII字符
NSMutableString*ascicharacters=[NSMutableString];
对于(NSInteger i=32;i<127;i++)
{
[字符格式:@“%c”,i];
}
NSCharacterSet*非SCIAICharacterSet=[[NSCharacterSet characterSetWithCharactersInString:asciiCharacters]InversedSet];
XML=[[XML组件由字符分隔集:非SCHIICharacterSet]组件由字符串连接:@”“];
NSData*data=[XML数据使用编码:NSUTF8StringEncoding];
NSXMLParser*parser=[[NSXMLParser alloc]initWithData:data];
[解析器setDelegate:self];
[语法分析器解析];
编辑:
NSXMLParser是一个可怕的工具。我已经在我的所有应用程序中成功地使用了RaptureXML。它超级容易使用,避免了所有这些非ascii字符的非意义 我知道会发生什么,我也有同样的问题 在解析器中查看
foundCharacters
方法
我有这样的想法:
if (!currentElementValue) {
currentElementValue = [[NSMutableString alloc] initWithString:string];
}
当发生特殊字符时,currentElementValue
刚刚停止获取
现在我的工作代码是:
if (!currentElementValue) {
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue appendString:string];
}
请记住在
didEndElement
方法的末尾将currentElementValue
设置为nil
,此对象没有为您做任何事情:NSString*XML=[NSString stringWithContentsOfURL:URL编码:NSASCIIStringEncoding错误:&error]代码>您似乎根本没有使用它。NSXMLParser
直接从URL
加载。您是否收到解析或验证错误?@Justin-您是对的,因为我正在将URL传递给XML解析器,所以操作XML字符串不会做任何事。有没有一种方法可以在-(void)解析器中修改xml的结果?To:Jesse-我没有收到任何错误,发生的是XML在命中第一个特殊字符后停止解析。我有更多的标签,一旦你收到了数据,它们就不会被读取,但是,你仍然需要将其解释为文本,这意味着你必须使用正确的编码。返回的数据不是UTF8,因此试图以这种方式解释它是不正确的。你关于使用NSURLConnection来避免阻塞的观点很好,但是OP可能是在后台线程上发出此请求,在后台线程中,同步调用并不是一件坏事,而且对于单行请求的简单性,肯定有一些话要说。谢谢Caleb-我稍微改变了我的问题。问题就在这里。NSXMLParser*parser=[[NSXMLParser alloc]initwithcontentsofull:URL];在-(void)解析器中:。。。如何修复返回的URL结果中的特殊字符?如果需要特殊字符怎么办?这里的“currentElementValue”是什么
if (!currentElementValue) {
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue appendString:string];
}