4

UPDATE: SOLUTION DOCUMENTED IN ANSWERS BELOW

I'm having trouble with RestKit mapping using the new @root @parent accessors in 0.20.3. I'm not sure if it's a bug or a misunderstanding of how to use the framework properly.

PROBLEM

The new concept of @root and @parent doesn't seem to be working for me.

EDIT: Removed a bunch of discussion about what I thought the problem was. I was way wrong so there is no need in digesting it. If the problem statement above applies to you... then this SO post might help get you going.

BACKGROUND

Example source XML can be downloaded here

The basic structure of the XML is as follows:

<locations>
  <location lat="38.8561" lon="-94.6654" timezone="UTC" city="Overland Park" region="KS" country="US" zipcode="66223" offset="0" local_offset_hours="-5">
    <sfc_ob>
      <attribute1></attribute1>
    </sfc_ob>
    <daily_summaries>
      <daily_summary>
        <attribute2> </attribute2>
      </daily_summary>
    </daily_summaries>
    <hourly_summaries>
      <hourly_summary>
        <attribute3></attribute3>
      </hourly_summary>
    </hourly_summaries>
  </location>
</locations>

My Core Data Entities are as follows:

enter image description here enter image description here enter image description here

RESTKIT RELATED CODE

- (GLWeatherManager *)init {
self = [super init];

// setup logging
RKLogConfigureByName("RestKit/Network*", RKLogLevelTrace);
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);

self.httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://weather.wdtinc.com"]];
[self.httpClient setDefaultHeader:@"Accept" value:RKMIMETypeXML];
[RKMIMETypeSerialization registerClass:[RKXMLReaderSerialization class] forMIMEType:@"application/xml"];
self.restKitManager = [[RKObjectManager alloc] initWithHTTPClient:self.httpClient];
self.restKitManager.managedObjectStore = [[RKManagedObjectStore alloc] initWithPersistentStoreCoordinator:[NSPersistentStoreCoordinator MR_defaultStoreCoordinator]];
[self.restKitManager.managedObjectStore createManagedObjectContexts];

// Locations
RKEntityMapping *locationMapping = [self buildMapForLocations];
RKEntityMapping *currentConditionsMapping = [self buildMapForCurrentConditions];
RKEntityMapping *dailySummariesMapping = [self buildMapForDailySummaries];
RKEntityMapping *hourlyForecastsMapping = [self buildMapForHourlyForecasts];

[locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"daily_summaries" toKeyPath:@"dailySummaries" withMapping:dailySummariesMapping]];
[locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"hourly_summaries" toKeyPath:@"hourlyForecasts" withMapping:hourlyForecastsMapping]];
[locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"sfc_ob" toKeyPath:@"currentConditions" withMapping:currentConditionsMapping]];


[dailySummariesMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil toKeyPath:@"location" withMapping:locationMapping]];
[hourlyForecastsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil toKeyPath:@"location" withMapping:locationMapping]];

RKResponseDescriptor *descriptor = [RKResponseDescriptor  responseDescriptorWithMapping:locationMapping pathPattern:@"/feeds/demofeeds20131031/mega.php" keyPath:@"locations.location" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];                        

// add mapping description to objectmanager
[self.restKitManager addResponseDescriptor:descriptor];

RKResponseDescriptor *descriptor2 = [RKResponseDescriptor responseDescriptorWithMapping:currentConditionsMapping pathPattern:@"/feeds/demofeeds20131031/mega.php" keyPath:@"locations.location.sfc_ob"                                                              statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

[self.restKitManager addResponseDescriptor:descriptor2];

RKResponseDescriptor *descriptor3 = [RKResponseDescriptor responseDescriptorWithMapping:dailySummariesMapping                                    pathPattern:@"/feeds/demofeeds20131031/mega.php"                                                 keyPath:@"locations.location.daily_summaries.daily_summary"                                          statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    [self.restKitManager addResponseDescriptor:descriptor3];

    RKResponseDescriptor *descriptor4 = [RKResponseDescriptor responseDescriptorWithMapping:hourlyForecastsMapping                                               pathPattern:@"/feeds/demofeeds20131031/mega.php"                                                                keyPath:@"locations.location.hourly_summaries.hourly_summary"
                                                                                statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    [self.restKitManager addResponseDescriptor:descriptor4];

// start the location manager to get the current location
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
[self.locationManager startUpdatingLocation];

self.locations = [NSMutableArray arrayWithArray:[Locations findAll]];

[self getMegaFeed];

return self;

}


- (RKEntityMapping *)buildMapForLocations {
RKEntityMapping *locationMapping = [RKEntityMapping mappingForEntityForName:@"Locations" inManagedObjectStore:self.restKitManager.managedObjectStore];
[locationMapping addAttributeMappingsFromDictionary:@{
 @"lat" : @"latitude",
 @"lon" : @"longitude",
 @"city" : @"city",
 @"region" : @"region",
 @"country" : @"country",
 @"zipcode" : @"zipcode",
 }];
locationMapping.identificationAttributes = [NSArray arrayWithObject:@"zipcode"];

return locationMapping;
}

    - (RKEntityMapping *)buildMapForCurrentConditions {
    // Current Conditions
    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"CurrentConditions" inManagedObjectStore:self.restKitManager.managedObjectStore];
    [mapping addAttributeMappingsFromDictionary:@{
     //@"stn" : @"stn",
     //@"location" : @"location",
     //@"stn_lat" : @"stnLatitude",
     //@"stn_lon" : @"stnLongitude",
     @"ob_time.text" : @"observationTime",
     @"day_of_week.text" : @"dayOfWeek",
     @"temp_C.text" : @"temperatureMetric",
     @"temp_F.text" : @"temperatureImperial",
     @"dewp_C.text" : @"dewPointMetric",
     @"dewp_F.text" : @"dewPointImperial",
     @"rh_pct.text" : @"relativeHumidity",
     @"wnd_dir.text" : @"windDirection",
     @"wnd_spd_mph.text" : @"windSpeedImperial",
     @"wnd_spd_kph.text" : @"windSpeedMetric",
     @"press_in.text" : @"pressureImperial",
     @"press_mb.text" : @"pressureMetric",
     @"wx.text" : @"conditionSummary",
     @"wx_code.text" : @"conditionCode",
     @"cld_cover.text" : @"cloudCover",
     @"visibility_ft.text" : @"visibilityImperial",
     @"visibility_m.text" : @"visibilityMetric",
     @"apparent_temp_F.text" : @"feelsLikeTemperatureImperial",
     @"apparent_temp_C.text" : @"feelsLikeTemperatureMetric",
     @"moon_phase.text" : @"moonPhase",
     @"sunrise_utc.text" : @"sunrise",
     @"sunset_utc.text" : @"sunset"
     }];

    [mapping setIdentificationAttributes:[NSArray arrayWithObjects:@"observationTime", nil]];

    return mapping;

}

- (RKEntityMapping *)buildMapForDailySummaries {
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"DailySummaries" inManagedObjectStore:self.restKitManager.managedObjectStore];
[mapping addAttributeMappingsFromDictionary:@{
 @"summary_date.text" : @"date",
 @"day_of_week.text" : @"dayOfWeek",
 @"max_temp_F.text" : @"tempMaxImperial",
 @"max_temp_C.text" : @"tempMaxMetric",
 @"min_temp_F.text" : @"tempMinImperial",
 @"min_temp_C.text" : @"tempMinMetric",
 @"wnd_spd_mph.text" : @"windSpeedImperial",
 @"wnd_spd_kph.text" : @"windSpeedMetric",
 @"min_wnd_spd_mph.text" : @"windSpeedMinImperial",
 @"min_wnd_spd_kph.text" : @"windSpeedMinMetric",
 @"max_wnd_spd_mph.text" : @"windSpeedMaxImperial",
 @"max_wnd_spd_kph.text" : @"windSpeedMaxMetric",
 @"wnd_gust_mph.text" : @"windGustImperial",
 @"wnd_gust_kph.text" : @"windGustMetric",
 @"wnd_dir.text" : @"windDirection",
 @"pop.text" : @"probabilityOfPrecipitation",
 @"wx.text" : @"conditionSummary",
 @"wx_code.text" : @"conditionCode",
 @"text_description.text" : @"textDescription",
 @"sunrise_utc.text" : @"sunrise",
 @"sunset_utc.text" : @"sunset",
 @"@root.locations.location.zipcode" : @"locationZipcode"
 }];
mapping.identificationAttributes = [NSArray arrayWithObjects:@"date", @"locationZipcode", nil];
[mapping addConnectionForRelationship:@"location" connectedBy:@{@"locationZipcode": @"zipcode"}];
return mapping;

}

- (RKEntityMapping *)buildMapForHourlyForecasts {
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"HourlyForecasts" inManagedObjectStore:self.restKitManager.managedObjectStore];
[mapping addAttributeMappingsFromDictionary:@{
 @"day_of_week_utc.text" : @"dayOfWeek",
 @"time_utc.text" : @"forecastTime",
 @"temp_C.text" : @"temperatureMetric",
 @"temp_F.text" : @"temperatureImperial",
 @"dewp_C.text" : @"dewPointMetric",
 @"dewp_F.text" : @"dewPointImperial",
 @"app_temp_C.text" : @"feelsLikeTemperatureMetric",
 @"app_temp_F.text" : @"feelsLikeTemperatureImperial",
 @"rh_pct.text" : @"relativeHumidity",
 @"wx.text" : @"conditionSummary",
 @"wx_code.text" : @"conditionCode",
 @"day_night.text" : @"dayNight",
 @"pop.text" : @"probabilityOfPrecipitation",
 @"sky_cov_pct.text" : @"skyCoverPercent",
 @"wnd_dir.text" : @"windDirection",
 @"wnd_dir_degs.text" : @"windDirectionDegrees",
 @"wnd_spd_mph.text" : @"windSpeedImperial",
 @"wnd_spd_kph.text" : @"windSpeedMetric",
 @"@root.locations.location.zipcode" : @"locationZipcode"
 }];

mapping.identificationAttributes = [NSArray arrayWithObjects:@"forecastTime", @"locationZipcode", nil];
[mapping addConnectionForRelationship:@"location" connectedBy:@{@"locationZipcode": @"zipcode"}];
return mapping;

}

- (void)getMegaFeed {
for (Locations *location in self.locations) {
    NSString *path = [NSString stringWithFormat:@"/feeds/demofeeds20131031/mega.php?ZIP=%@&UNITS=all",location.zipcode];
    // fetch data
    [self.restKitManager getObjectsAtPath:path
                               parameters:nil
                                  success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

                                      NSArray *mappedObjects = [mappingResult array];
                                      NSMutableArray *validObjectIDs = [[NSMutableArray alloc] initWithCapacity:[mappedObjects count]];

                                      for (NSManagedObject *object in mappedObjects) {
                                          NSManagedObjectID *moID = [object objectID];
                                          [validObjectIDs addObject:moID];
                                      }
                                      [self notifyObservers:@selector(megaFeedDidFinish:location:) withObject:validObjectIDs withObject:location];


                                  }
                                  failure:^(RKObjectRequestOperation *operation, NSError *error) {
                                      [REUtility showDefaultAlertWithError:error];
                                      [RELog error:@"%s Hit error:%@", __func__, error];
                                  }];

}

}

radesix
  • 5,834
  • 5
  • 24
  • 39

2 Answers2

5

I think the problem is the key paths you're using in the response descriptors for the mappings where you try to use @root. When you specify a keypath on the response descriptor you are effectively changing the @root object because you are diving into the content to a specified depth and that depth becomes the root for that mapping. If you debug during the mapping process and look at the supplied metadata you should be able to see / verify this.

I'm not clear on why you have so many different response descriptors. It would seem more logical to have one response descriptor for locations whose mapping defines all of the relationships between all of the different parts (and their mappings). Working in this way you would have much simpler code and you would also have access to @root / @parent.

Wain
  • 118,658
  • 15
  • 128
  • 151
  • I hear what you are saying and it makes sense. Let me do some poking around today. If I can confirm your statements I'll award the correct answer points. Thank you so much for your input! – radesix Oct 08 '13 at 13:18
  • I don't quite understand how to build one giant "locations" mapping. The top level of the response doesn't get mapped into a Core Data entity like the rest of the objects do. This is why I had broken things out individually. Can I mix RKObjectMapping and RKEntityMapping objects in the same workflow? – radesix Oct 08 '13 at 14:00
  • You would have one response descriptor with a keypath of locations. This is an array so RestKit will iterate over the array and apply your response descriptor mapping to each item. This should create one `Location` per iteration and any nested instances (based on the mapping relationships to other mappings). – Wain Oct 08 '13 at 14:06
  • you are THE man! It took a bit of trial and error for me to get it squared away but you set me on the right path! When I get a chance in the next day or two I'll post the final code blocks with the changes I made so others can benefit. – radesix Oct 08 '13 at 16:02
1

Fellow Stacker

This is the solution that has materialized as a result of Wain's suggestion above. I am posting here not to collect points but to keep the long contents of both the problem and the final solution separate. Please award any upvotes to @Wain, I am simply trying to post a concise problem-to-solution example regarding this issue.

I find RestKit to be one of the most awesome (for several reasons) 3rd party framework I have ever seen. There is a lot of community involvement; however, documentation and examples are sparse for "out of bounds" or uncommon scenarios and usages. I suspect most people use RestKit with JSON and complex real world XML examples are sparse. I hope this helps others who have the same type of issue.

SOLUTION

Wain was correct in the sense that I was building multiple response descriptors targeting each point in the hierarchy of the XML (available in the problem above) I was after. This was preventing RestKit from understanding that there was ever a (root) or (parent) to access.

Because I needed to map these to multiple entities in Core Data I should have had one large response descriptor at the highest tag level of the XML.

That meant if I map the single (in my xml) high level locations tag and I have properly configured the RestKit relationships it will do the rest for you.

IMPLEMENTATION

The first thing I realized was that I didn't care about the high level Locations tag in the XML and I didn't need to map it to a Core Data Entity so I built an RKObjectMapping instead of an RKEntityMapping to handle the processing of the high level tag in the XML.

The complete solution is below but I'll walk through the changes.

Note the new RKObjectMapping *locationsMapping = [self buildMapForLocations]; and the corresponding method.

I then needed to tell the new locationsMapping about the Location entity to be mapped to Core Data

[locationsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"location" toKeyPath:@"location"  withMapping:locationMapping]];

The next big changes, thanks to Wain, were the keypath changes to the relationships as follows:

[locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"daily_summaries.daily_summary" toKeyPath:@"dailySummaries" withMapping:dailySummariesMapping]];
[locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"hourly_summaries.hourly_summary" toKeyPath:@"hourlyForecasts" withMapping:hourlyForecastsMapping]];
[locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"sfc_ob" toKeyPath:@"currentConditions" withMapping:currentConditionsMapping]];

Here we tell the locationMapping (that maps to Core Data) where we are mapping from in the source XML to where we are going in Core Data. Since we are on the Location mapping, in the source XML the keyPath to my dailySummaries (entity) is "daily_summaries.daily_summary". Likewise, the correct keyPath to hourlyForecasts was "hourly_summaries.hourly_summary" and from location in the XML "sfc_ob" maps to currentConditions (entity).

Finally all of my response descriptors went away except one easy, simple response descriptor.

RKResponseDescriptor *descriptor = [RKResponseDescriptor responseDescriptorWithMapping:locationsMapping
                                                                                method:RKRequestMethodGET
                                                                           pathPattern:@"/feeds/demofeeds20131031/mega.php"
                                                                               keyPath:@"locations"
                                                                           statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[self.restKitManager addResponseDescriptor:descriptor];

Everything in the success block of the call to RestKit in the problem statement (above) was eliminated as everything including relationships had all been mapped properly. Note that all of the problem statement code for the mappings were still valid except for a minor tweak to the @root @parent aspect of the solution.

When mapping the daily summaries and hourly forecasts I still needed to get the zipcode from the location to be populated into the Core Data entity so that RestKit can use this as a key on future calls to check the database to see if a record with this key already exists (to update instead of create).

I tweaked the @ mappings to grab the zipcode from location. Note the desired use of the @parent.@parent traversal of the hierarchy as follows:

- (RKEntityMapping *)buildMapForDailySummaries {
    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"DailySummaries" inManagedObjectStore:self.restKitManager.managedObjectStore];
    [mapping addAttributeMappingsFromDictionary:@{
     @"summary_date.text" : @"date",
     @"day_of_week.text" : @"dayOfWeek",
     @"max_temp_F.text" : @"tempMaxImperial",
     @"max_temp_C.text" : @"tempMaxMetric",
     @"min_temp_F.text" : @"tempMinImperial",
     @"min_temp_C.text" : @"tempMinMetric",
     @"wnd_spd_mph.text" : @"windSpeedImperial",
     @"wnd_spd_kph.text" : @"windSpeedMetric",
     @"min_wnd_spd_mph.text" : @"windSpeedMinImperial",
     @"min_wnd_spd_kph.text" : @"windSpeedMinMetric",
     @"max_wnd_spd_mph.text" : @"windSpeedMaxImperial",
     @"max_wnd_spd_kph.text" : @"windSpeedMaxMetric",
     @"wnd_gust_mph.text" : @"windGustImperial",
     @"wnd_gust_kph.text" : @"windGustMetric",
     @"wnd_dir.text" : @"windDirection",
     @"pop.text" : @"probabilityOfPrecipitation",
     @"wx.text" : @"conditionSummary",
     @"wx_code.text" : @"conditionCode",
     @"text_description.text" : @"textDescription",
     @"sunrise_utc.text" : @"sunrise",
     @"sunset_utc.text" : @"sunset",
     @"@parent.@parent.zipcode" : @"locationZipcode"
     }];
    mapping.identificationAttributes = [NSArray arrayWithObjects:@"date", @"locationZipcode", nil];
    [mapping addConnectionForRelationship:@"location" connectedBy:@{@"locationZipcode": @"zipcode"}];


    return mapping;
}

- (RKEntityMapping *)buildMapForHourlyForecasts {
    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"HourlyForecasts" inManagedObjectStore:self.restKitManager.managedObjectStore];
    [mapping addAttributeMappingsFromDictionary:@{
     @"day_of_week_utc.text" : @"dayOfWeek",
     @"time_utc.text" : @"forecastTime",
     @"temp_C.text" : @"temperatureMetric",
     @"temp_F.text" : @"temperatureImperial",
     @"dewp_C.text" : @"dewPointMetric",
     @"dewp_F.text" : @"dewPointImperial",
     @"app_temp_C.text" : @"feelsLikeTemperatureMetric",
     @"app_temp_F.text" : @"feelsLikeTemperatureImperial",
     @"rh_pct.text" : @"relativeHumidity",
     @"wx.text" : @"conditionSummary",
     @"wx_code.text" : @"conditionCode",
     @"day_night.text" : @"dayNight",
     @"pop.text" : @"probabilityOfPrecipitation",
     @"sky_cov_pct.text" : @"skyCoverPercent",
     @"wnd_dir.text" : @"windDirection",
     @"wnd_dir_degs.text" : @"windDirectionDegrees",
     @"wnd_spd_mph.text" : @"windSpeedImperial",
     @"wnd_spd_kph.text" : @"windSpeedMetric",
     @"@parent.@parent.zipcode" : @"locationZipcode"
     }];

    mapping.identificationAttributes = [NSArray arrayWithObjects:@"forecastTime", @"locationZipcode", nil];
    [mapping addConnectionForRelationship:@"location" connectedBy:@{@"locationZipcode": @"zipcode"}];
    return mapping;
}
- (RKObjectMapping *)buildMapForLocations {
    RKObjectMapping *locationsMapping = [[RKObjectMapping alloc] initWithClass:[WDTMegaFeedResponse class]];
    [locationsMapping addAttributeMappingsFromDictionary:@{
     @"language.text" : @"language",
                                                           }];
    return locationsMapping;
}

The changes to the mappings here and the changes below is the complete solution for this use case.

- (GLWeatherManager *)init {
    self = [super init];

    self.cloud = [[Kumulos alloc] init];
    [self.cloud setDelegate:self];

    // Check to see if the states have been loaded
    NSArray *states = [States findAllSortedBy:@"code" ascending:YES];
    if ([states count] == 0) {
        [self.cloud getStates];
    }

    // setup logging
    RKLogConfigureByName("RestKit/Network*", RKLogLevelTrace);
    RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);

    // initialize the network layer and ensure we are using the same store magical record is using
    self.httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://weather.wdtinc.com"]];
    [self.httpClient setDefaultHeader:@"Accept" value:RKMIMETypeXML];
    [RKMIMETypeSerialization registerClass:[RKXMLReaderSerialization class] forMIMEType:@"application/xml"];

    self.restKitManager = [[RKObjectManager alloc] initWithHTTPClient:self.httpClient];
    self.restKitManager.managedObjectStore = [[RKManagedObjectStore alloc] initWithPersistentStoreCoordinator:[NSPersistentStoreCoordinator MR_defaultStoreCoordinator]];
    [self.restKitManager.managedObjectStore createManagedObjectContexts];

    // Locations

    RKObjectMapping *locationsMapping = [self buildMapForLocations];

    RKEntityMapping *hourlyForecastsMapping = [self buildMapForHourlyForecasts];
    RKEntityMapping *dailySummariesMapping = [self buildMapForDailySummaries];
    RKEntityMapping *currentConditionsMapping = [self buildMapForCurrentConditions];
    RKEntityMapping *locationMapping = [self buildMapForLocation];

    [locationsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"location" toKeyPath:@"location"  withMapping:locationMapping]];

    [locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"daily_summaries.daily_summary" toKeyPath:@"dailySummaries" withMapping:dailySummariesMapping]];
    [locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"hourly_summaries.hourly_summary" toKeyPath:@"hourlyForecasts" withMapping:hourlyForecastsMapping]];
    [locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"sfc_ob" toKeyPath:@"currentConditions" withMapping:currentConditionsMapping]];

    RKResponseDescriptor *descriptor = [RKResponseDescriptor responseDescriptorWithMapping:locationsMapping
                                                                                    method:RKRequestMethodGET
                                                                               pathPattern:@"/feeds/demofeeds20131031/mega.php"
                                                                                   keyPath:@"locations"
                                                                               statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
    [self.restKitManager addResponseDescriptor:descriptor];
}

Also some might find the header file of the RKObjectMapping object used to capture the high level XML tag useful.

#import <Foundation/Foundation.h>
#import "Locations.h"

@interface WDTMegaFeedResponse : NSObject

@property (nonatomic, strong) NSString *language;
@property (nonatomic, strong) Locations *location;

@end
radesix
  • 5,834
  • 5
  • 24
  • 39