2014-12-05 4 views
4

Я использую AFNetworking-2 с ответом JSON, и он отлично работает, и теперь мне нужно преобразовать его в XML вместо использования JSON, потому что ответ сервера находится в XML. После того, как я обыскал, я добрался до этого кода, но он не работает.Проблема с запросом XML-запроса AFNetworking

С Чарльзом я нашел запрос неправильно "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); 
} 
+0

Вы используете Charles: Вы сравнили, на что похожи эти два запроса?Очевидно, что они разные, и у вас есть идеальный инструмент для поиска запросов. – Rob

+0

Кстати, ваш вызов '[urlConnection start]' должен быть удален. – Rob

+0

Я удалил '[urlConnection start]' ... В NSURLConnection запрос выглядит так: НО в AFNetworking 'Faild для анализа XML-документа Причина: Содержимое не допускается в прологе. Строка: 1 столбец: Это сообщение отправлено в Charles request XML. @Rob – CAN

ответ

3

При использовании 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 - для большинства приложений гораздо проще работать.

+0

Извините за поздний ответ по некоторым причинам. Он отлично работает с 'didReceiveData: (NSData *) data' и' didStartElement: (NSString *) elementName'. – CAN

3

Чтобы расширить ответ Аарона (который вы, вероятно, следует принимать), если ваш сервер ожидает запрос 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, я бы посоветовал вам обратиться к Event-Driven XML Programming Guide от Apple или к Google NSXMLParser примеру или к учебнику NSXMLParser для получения дополнительной информации.


Кстати, я замечаю, что вы строите строку XML вручную. Некоторые поля (особенно пароль) могут содержать некоторые символы, зарезервированные в пределах полей XML. Поэтому, если вы создаете свой XML вручную, убедитесь, что вы заменили , > и & значениями, которые вы вставляете в свой XML с &lt;, &gt; и &amp;, соответственно.

+0

Извините за поздний ответ по некоторым причинам. Спасибо за объяснение. Я проанализировал свои данные с помощью 'didReceiveData: (NSData *) data' и' didStartElement: (NSString *) elementName', и он работает нормально. – CAN

Смежные вопросы