AFNetworking XML 请求问题
Posted
技术标签:
【中文标题】AFNetworking XML 请求问题【英文标题】:AFNetworking XML Request Issue 【发布时间】:2014-12-05 14:02:03 【问题描述】:我正在使用带有 JSON 响应的 AFNetworking-2
,它工作正常,现在我必须将其转换为 XML 而不是使用 JSON,因为服务器响应是 XML 格式的。在我搜索后,我使用了这段代码,但它不起作用。
我发现查尔斯的请求是错误的"Fail to parse data (org.xml.sax.SAXParseException: Content not allowed is prolog)"
请问我的问题在哪里?
我的代码:
NSString *urlString = BaseURLString;
NSURL *url = [[NSURL alloc] initWithString:urlString];
NSString *value = @"<r_PM act=\"login\" loginname=\"1234\" password=\"12345678\" />";
NSString *message = [value stringByReplacingOccurrencesOfString:@"[\\\"" withString:@""];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod: @"POST"];
[request setValue:@"text/xml" forHTTPHeaderField:@"content-type"];
[request setHTTPBody:[[NSString stringWithFormat:@"%@",message] dataUsingEncoding:NSUTF8StringEncoding]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
// Make sure to set the responseSerializer correctly
operation.responseSerializer = [AFXMLParserResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
NSXMLParser *XMLParser = (NSXMLParser *)responseObject;
[XMLParser setShouldProcessNamespaces:YES];
// Leave these commented for now (you first need to add the delegate methods)
XMLParser.delegate = self;
[XMLParser parse];
failure:^(AFHTTPRequestOperation *operation, NSError *error)
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Weather"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alertView show];
];
[operation start];
这是一个运行良好的示例:
- (void)viewDidLoad
[super viewDidLoad];
NSString *value = @"<r_PM act=\"login\" loginname=\"1234\" password=\"12345678\"/>";
NSString *authenticationURL = @"http://demo.example.com/ex/mob/";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:authenticationURL]];
NSString *message = [value stringByReplacingOccurrencesOfString:@"[\\\"" withString:@""];
[request setHTTPMethod: @"POST"];
[request setValue:@"text/xml" forHTTPHeaderField:@"content-type"];
[request setHTTPBody:[[NSString stringWithFormat:@"%@",message] dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[urlConnection start];
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
NSString *responseText = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", responseText);
【问题讨论】:
您正在使用 Charles:您是否比较了这两个请求的样子?显然它们是不同的,您拥有查看请求的理想工具。 顺便说一句,你对[urlConnection start]
的调用应该被删除。
我已删除 [urlConnection start]
... 在 NSURLConnection 中,请求看起来像这样 <?xml-stylesheet type="text/xsl" href="/pr/xsl/genel/error.xsl"?> <root> <res t="-2"> <a o="MS" d="Wrong req" /> </res> </root>
【参考方案1】:
当您使用AFHTTPRequestSerializer
时,您的正文是使用 URL 表单参数编码创建的。您的非 AFNetworking 示例使用 XML,因此正文看起来不同。
你会想做这样的事情:
不要使用POST:…
方便的方法,而是使用序列化程序,然后手动设置和排队您的操作:
NSMutableURLRequest *request = [requestSerializer requestWithMethod:@"POST" URLString:[[NSURL URLWithString:urlString] absoluteString] parameters:parameters error:nil];
request.HTTPBody = [[NSString stringWithFormat:@"%@",message] dataUsingEncoding:NSUTF8StringEncoding];
AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request success:<# success block #> failure:<# failure block #>];
[manager.operationQueue addOperation:operation];
如果你不得不这样做,你可能想要继承 AFHTTPRequestSerializer
并为你的服务器制作一个自定义序列化程序。
但实际上,您应该告诉您的服务器团队继续接受 JSON - 对于大多数应用程序来说,使用它要简单得多。
【讨论】:
抱歉,由于某些原因回复晚了。它与didReceiveData:(NSData *)data
和didStartElement:(NSString *)elementName
一起工作正常。【参考方案2】:
为了扩展 Aaron 的回答(您可能应该接受),如果您的服务器期待 XML 请求,并且正在发送 XML 响应,您可以执行以下操作:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPBody:[xmlRequestString dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/xml" forHTTPHeaderField:@"Accept"];
NSOperation *operation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject)
NSXMLParser *parser = responseObject;
parser.delegate = self;
if (![parser parse])
// handle parsing error here
else
// use parsed data here
failure:^(AFHTTPRequestOperation *operation, NSError *error)
// handle network related errors here
];
[manager.operationQueue addOperation:operation];
在上面,我设置了两个标头,Content-Type
(通知服务器您正在发送 XML 请求)和 Accept
(通知服务器您正在等待并将接受 XML 响应)。这些不一定是必需的,但可能是很好的做法。这里有时还会使用一些变体(例如,text/xml
是可能的,或者也有一些其他相关的 Content-Type
值),但这仅取决于您的服务器的期望。但目标是成为一个优秀的 HTTP 公民并指定这些标头。
显然,这假设您还实现了 NSXMLParserDelegate
方法以便实际解析 XML 响应,但这超出了本问题的范围。如果您不熟悉NSXMLParser
,我建议您查看Apple 的Event-Driven XML Programming Guide 或谷歌“NSXMLParser 示例”或“NSXMLParser 教程”了解更多信息。
顺便说一句,我注意到您正在手动构建 XML 字符串。某些字段(尤其是密码)可能包含一些在 XML 字段中保留的字符。因此,如果您手动构建 XML,请确保将嵌入 XML 中的值中的 &lt;
、&gt;
和 &amp;
分别替换为 &lt;
、&gt;
和 &amp;
。
【讨论】:
抱歉,由于某些原因回复晚了。谢谢你的解释。我已经用didReceiveData:(NSData *)data
和didStartElement:(NSString *)elementName
解析了我的数据,它工作正常。以上是关于AFNetworking XML 请求问题的主要内容,如果未能解决你的问题,请参考以下文章