2013-12-05 4 views
9

Я довольно новичок в iOS и пытаюсь выполнить запрос REST и получить некоторые XML-данные, проанализировать их и, в идеале, разместить в пользовательском объекте. Но на данный момент я застрял в получении XML-данных.Анализ XML с AFNetworking

Я нашел этот фрагмент кода на Github/AFNetworking ..

- (void) fetchInterestData{ 
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
manager.responseSerializer = [AFXMLResponseSerializer new]; 
NSDictionary *parameters = @{@"foo": @"bar"}; 
[manager POST:@"http://www.raywenderlich.com/downloads/weather_sample/weather.php?format=json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSLog(@"JSON: %@", responseObject); 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    NSLog(@"Error: %@", error); 
}]; 
} 

Он работает и получает объект JSON. Но я хочу получить XML.

Если я использую http://www.raywenderlich.com/downloads/weather_sample/weather.php?format=xml, вместо этого есть объект xml. Но теперь код полностью разрушается. Я надеялся хотя бы получить xml как строковый объект.

Что мне нужно изменить, чтобы принести XML и предположительно, я хочу принести XML-объект следующей структуры:

<RootNode> 
<Banks> 
    <Bank> 
    <BankId>17</BankId> 
    <BankName>Bluestep</BankName> 
    <BankUrl>http://www.bluestep.se</BankUrl> 
    <BankImage> 
    http://smartkalkyl.se/smartfiles/layout/banklogos/bluestep.png 
    </BankImage> 
    <Rates> 
     <Rate> 
      <RateDate>2013-12-05</RateDate> 
      <RateType>5</RateType> 
      <RateInterest>6,23</RateInterest> 
      <RateDescription/> 
      <RateBefore>6,27</RateBefore> 
      <RateChange>False</RateChange> 
      <RateBeforeDate>2013-08-13</RateBeforeDate> 
    </Rate> 
    </Rates> 
    </Bank> 
    <Bank> 
    ... 

Как я могу сделать это?

UPDATE: Новый код ..

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
AFHTTPRequestSerializer * requestSerializer = [AFHTTPRequestSerializer serializer]; 
NSString *ua = @"Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25"; 
[requestSerializer setValue:ua forHTTPHeaderField:@"User-Agent"]; 
[requestSerializer setValue:@"application/xml" forHTTPHeaderField:@"Content-type"]; 
manager.requestSerializer = requestSerializer; 

NSDictionary *parameters = @{@"foo": @"bar"}; 


[manager POST:@"http://smartkalkyl.se/rateapp.aspx?user=xxxx&pass=xxx" 
    parameters:parameters 
success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSData * data = (NSData *)responseObject; 
    self.fetchedXML = [NSString stringWithUTF8String:[data bytes]]; 
    //NSLog(@"Response string: %@", self.fetchedXML); 
} 
failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    NSLog(@"Error: %@", error); 
}]; 

Но это дает мне ошибку ..

2013-12-06 00:04:10.657 TabbedDemo[38335:a0b] Error: Error Domain=AFNetworkingErrorDomain Code=-1016 "Request failed: unacceptable content-type: text/xml" UserInfo=0x8d80ac0 {NSErrorFailingURLKey=http://smartkalkyl.se/rateapp.aspx?user=xxxx&pass=xxxx, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x8a75230> { URL: http://smartkalkyl.se/rateapp.aspx?user=xxxx&pass=xxxx } { status code: 200, headers { 
"Cache-Control" = private; 
"Content-Encoding" = deflate; 
"Content-Length" = 1260; 
"Content-Type" = "text/xml; charset=iso-8859-1"; 
Date = "Thu, 05 Dec 2013 23:03:47 GMT"; 
Server = "Microsoft-IIS/7.5"; 
"Set-Cookie" = "ASP.NET_SessionId=ad3zikxbh4bcawxulkhwt2j3; path=/; HttpOnly"; 
"X-AspNet-Version" = "4.0.30319"; 
"X-Powered-By" = "UrlRewriter.NET 2.0.0, ASP.NET"; 
} }, NSLocalizedDescription=Request failed: unacceptable content-type: text/xml} 

Любая идея, что может быть проблема?

Я делаю аналогичную операцию в Android-версии приложения, и это код, который работает там и работает. Я никогда не ставил любой тип контента там ..

// defaultHttpClient 
DefaultHttpClient httpClient = new DefaultHttpClient(); 
HttpProtocolParams.setUserAgent(httpClient.getParams(), 
System.getProperty("http.agent")); 
HttpPost httpPost = new HttpPost(url); 

HttpResponse httpResponse = httpClient.execute(httpPost); 
HttpEntity httpEntity = httpResponse.getEntity(); 
xml = EntityUtils.toString(httpEntity); 
+0

Ну, вы не должны предполагать AFN является XML-парсер, или JSON парсер. Есть только некоторые удобные функции, такие как «Серийный отладчик JSON Response», который строго не требуется, чтобы быть частью сетевой библиотеки. Вы можете выполнить эту же функцию JSON Serializer с несколькими строками кода. Анализ XML более сложный, но вы можете написать собственный XML-сериализатор или использовать «встроенный» 'AFXMLParserResponseSerializer', если это соответствует вашим потребностям. – CouchDeveloper

+0

Разбор XML - это моя вторичная цель. Первоначально я просто хочу получить XML с сервера в виде строки или аналогичной. –

ответ

16

На основе вашего обновленного кода, вам нужно добавить сериалайзер ответа, и вы также должны перевести NSData правильно:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
AFHTTPRequestSerializer * requestSerializer = [AFHTTPRequestSerializer serializer]; 
AFHTTPResponseSerializer * responseSerializer = [AFHTTPResponseSerializer serializer]; 

NSString *ua = @"Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25"; 
[requestSerializer setValue:ua forHTTPHeaderField:@"User-Agent"]; 
// [requestSerializer setValue:@"application/xml" forHTTPHeaderField:@"Content-type"]; 
responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/xml", nil]; 
manager.responseSerializer = responseSerializer; 
manager.requestSerializer = requestSerializer; 

NSDictionary *parameters = @{@"foo": @"bar"}; 

[manager POST:@"http://smartkalkyl.se/rateapp.aspx?user=xxxxx&pass=xxxxxx" 
    parameters:parameters 
     success:^(AFHTTPRequestOperation *operation, id responseObject) { 
      NSData * data = (NSData *)responseObject; 
      self.fetchedXML = [NSString stringWithCString:[data bytes] encoding:NSISOLatin1StringEncoding]; 
      NSLog(@"Response string: %@", self.fetchedXML); 
     } 
     failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
      NSLog(@"Error: %@", error); 
     }]; 

Ваш ответ возвращается как tex t/xml, а сериализатор ответа по умолчанию должен быть установлен так, чтобы принять это.

Данные не возвращаются как UTF8, а ascii, поэтому нам также необходимо установить его соответствующим образом.

Я дал ему выстрел в симулятор, и он работает на моем конце.

Редактировать: кажется, данные в формате ISO латинского-1. моя вина.

+0

Хороший ответ на обновленный вопрос! : D – Joiningss

+0

Спасибо! Это сделал трюк! : D –

12
  1. При использовании AFXMLResponseSerializer в AFHTTPRequestOperationManager'sresponseSerializer, то responseObject в успех блока является NSXMLParser объект, вы должны implemente NSXMLParser's делегат и синтаксического анализа XML

  2. Если вы хотите, чтобы получить XML как строка object.Use код ниже:

AFHTTPResponseSerializer Использование, затем закодировать данные ответа на строку

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
    manager.responseSerializer = [AFHTTPResponseSerializer new]; 
    NSDictionary *parameters = @{@"foo": @"bar"}; 
    [manager POST:@"http://www.raywenderlich.com/downloads/weather_sample/weather.php?format=xml" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { 
     NSData * data = (NSData *)responseObject; 
     NSLog(@"Response string: %@", [NSString stringWithUTF8String:[data bytes]]); 
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
     NSLog(@"Error: %@", error); 
    }]; 

UPDATE

набор User-Agent:

AFHTTPRequestSerializer * requestSerializer = [AFHTTPRequestSerializer serializer]; 
    [requestSerializer setValue:@"your user agent" forHTTPHeaderField:@"User-Agent"]; 
    manager.requestSerializer = requestSerializer; 
+0

Похоже, что он может работать, но в моем реальном URL мне нужно предоставить пользовательский агент. Как я могу это сделать? –

+0

@SebastianL Мой ответ обновлен, просто попробуйте: D – Joiningss

+0

Спасибо @Joiningss! Я все еще получаю одну проблему, хотя ... Я обновил основную проблему с помощью нового кода и журнала ошибок, которые я не понимаю. Я установил контент-тип как заголовок, но все же он жалуется. –

6

Эта библиотека является лучшим ->https://github.com/nicklockwood/XMLDictionary

NSURL *URL = [NSURL URLWithString:@"http://maps.googleapis.com/maps/api/directions/xml?origin=Toronto&destination=Montreal&sensor=false"]; 
NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 
operation.responseSerializer = [AFXMLDictionaryResponseSerializer serializer]; 
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 

    NSDictionary *d0 = [NSDictionary dictionaryWithXMLParser:(NSXMLParser*)responseObject]; 
    NSLog(@"d0:%@", d0); 
} failure:nil]; 

[operation start];