Parsing XML with AFNetworking

18,849

Solution 1

Based on your updated code, you need to add a response serializer, and you also need to translate the NSData properly:

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);
      }];

Your response is coming back as text/xml, and the default response serializer needs to be set to accept that.

The data isn't coming back as UTF8 but ascii, so we need to set that appropriately as well.

I gave it a shot in the simulator and it's working on my end.

edit: seems the data is in ISO latin-1 format. my bad.

Solution 2

  1. When you use AFXMLResponseSerializer as AFHTTPRequestOperationManager's responseSerializer, the responseObject in success block is a NSXMLParser object, you should implemente NSXMLParser's delegate,and parsing xml

  2. If you want to get the xml as a string object.Use the code below:

Using AFHTTPResponseSerializer, then encode the response data to string

    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

set User-Agent:

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

Solution 3

This library is the best -> 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];

Solution 4

you can try to use XmlReader to do what you want, it's pretty simple. Look here How to reloadData in tableView with didSelectedRowAtIndexPath and call group of methods in it

Share:
18,849
Sebastian L
Author by

Sebastian L

Updated on July 21, 2022

Comments

  • Sebastian L
    Sebastian L almost 2 years

    I am fairly new with iOS and is trying to do a REST request and fetch some XML data, parse that and ideally put into a custom Object. But for now I am stuck with the getting XML data.

    I found this code snippet on 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);
    }];
    }
    

    It works and fetches a JSON object. But I want to get the XML..

    If I use http://www.raywenderlich.com/downloads/weather_sample/weather.php?format=xml instead there is an xml object. But now the code breaks down completely. I was hoping to at least get the xml as a string object.

    What do I need to change to fetch the xml and assumingly I want to fetch a xml object of following structure:

    <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>
       ...
    

    How can I do that?

    UPDATE: New code..

    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);
    }];
    

    But this gives me an 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}
    

    Any idea what could be the problem?

    I am doing similar operation in the Android version of the app and this is the code that works there and that work. I never set any content type there..

    // 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);
    
  • Sebastian L
    Sebastian L over 10 years
    This looks like it can work but in my real URL I need to supply a user agent. How can I do this?
  • Sebastian L
    Sebastian L over 10 years
    Thanks @Joiningss! I still get one issue though... I updated the main issue with new code and the error log which I don't understand. I set content-type as a header but still it complains..
  • Joiningss
    Joiningss over 10 years
    @SebastianL KaosDG's answer is right. You miss response serializer and the response charset is iso-8859-1