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 中,请求看起来像这样 但在 AFNetworking @987654327 @此消息在 Charles 请求 XML 中。 @Rob 在请求中?还是回应?您可以仔细检查一下,因为在响应中看到这一点我不会感到惊讶,但在请求中看到这一点没有意义。 @Rob 我仔细检查了它是否在请求中。回复是&lt;?xml-stylesheet type="text/xsl" href="/pr/xsl/genel/error.xsl"?&gt; &lt;root&gt; &lt;res t="-2"&gt; &lt;a o="MS" d="Wrong req" /&gt; &lt;/res&gt; &lt;/root&gt; 【参考方案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 *)datadidStartElement:(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 中的值中的 &amp;lt;&amp;gt;&amp;amp; 分别替换为 &amp;lt;&amp;gt;&amp;amp;

【讨论】:

抱歉,由于某些原因回复晚了。谢谢你的解释。我已经用didReceiveData:(NSData *)datadidStartElement:(NSString *)elementName 解析了我的数据,它工作正常。

以上是关于AFNetworking XML 请求问题的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 AFNetworking Objective-C 获取 XML 响应的内部节点

AFNetWorking 网络请求转载

AFN请求问题

AFN3.0封装

iOS AFNetworking 3.0以上使用

AFNetWorking3.0 处理请求头 和 请求内容