I don't know what your model is but if I assume a straighforward tree-structured model PresetInfo > Modality > Body, this code is the design pattern I usually use. If you don't actually need to load a model, but instead just extract a specific data element, look at the XPath query in PresetInfo.parseXmlElement, and how I get attribute and element values in the other parseXmlElements.
The model interface. I used arrays for the lists, if you need keyed access to list elements, you could use dictionaries. The top-level class PresetInfo contains methods to read the XML from a file.
@interface ModelBase : NSObject
- (id)initWithXmlElement:(GDataXMLElement *)element;
- (void)parseXmlElement:(GDataXMLElement *)element;
@end
@interface PresetInfo : ModelBase
@property NSMutableArray *modalities;
- (id)initWithPath:(NSString *)path;
- (id)initWithXmlString:(NSString *)xmlString;
@end
@interface Modality : ModelBase
@propertyNSString *type;
@propertyNSMutableArray *bodies;
@end
@interface Body : ModelBase
@propertyNSString *part;
@propertyNSInteger ww;
@propertyNSInteger wl;
@end
The model implementation.
@implementation ModelBase
- (id)initWithXmlElement:(GDataXMLElement *)element
{
if (self = [self init]) {
[self parseXmlElement:element];
}
returnself;
}
- (void)parseXmlElement:(GDataXMLElement *)element {
[NSExceptionraise:NSInternalInconsistencyExceptionformat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];
// Objective-C has no abstract methods
}
@end
@implementation PresetInfo
- (id)init
{
if (self = [super init]) {
self.modalities = [[NSMutableArray alloc] init];
}
returnself;
}
- (id)initWithPath:(NSString *)path
{
NSError *error = nil;
NSStringEncoding *usedEncoding = nil;
NSString *xmlString = [NSString stringWithContentsOfFile:path usedEncoding:usedEncoding error:&error];
if (!xmlString)
NSLog(@"Error reading XML file: %@", [error localizedDescription]);
return [self initWithXmlString:xmlString];
}
- (id)initWithXmlString:(NSString *)xmlString
{
NSError *error = nil;
GDataXMLDocument *xmlDoc = [[GDataXMLDocument alloc] initWithXMLString:xmlString options:0 error:&error];
if (!xmlDoc)
NSLog(@"Error creating XML document: %@", [error localizedDescription]);
return [selfinitWithXmlElement:xmlDoc.rootElement];
}
- (void)parseXmlElement:(GDataXMLElement *)element
{
NSError *error = nil;
NSArray *nodes = [element nodesForXPath:@"presetinfo/modality" error:&error];
if (!nodes) {
NSLog(@"Response not found: %@", [error localizedDescription]);
return;
}
for (GDataXMLElement *element in nodes)
[self.modalities addObject:[[Modality alloc] initWithXmlElement:element]];
}
@end
@implementation Modality
- (id)init
{
if (self = [super init]) {
self.bodies = [[NSMutableArray alloc] init];
}
returnself;
}
- (void)parseXmlElement:(GDataXMLElement *)element {
GDataXMLNode *node = [element attributeForName:@"type"];
if (node) self.type = node.stringValue;
NSArray *nodes = [element elementsForName:@"body"];
for (GDataXMLElement *element in nodes)
[self.bodies addObject:[[Body alloc] initWithXmlElement:element]];
}
@end
@implementation Body
- (void)parseXmlElement:(GDataXMLElement *)element {
GDataXMLNode *node = [element attributeForName:@"PART"];
if (node) self.part = node.stringValue;
node = [element attributeForName:@"WW"];
if (node) self.ww = [node.stringValue integerValue];
node = [element attributeForName:@"WL"];
if (node) self.wl = [node.stringValue integerValue];
}
@end
Example of loading your XML into the model and showing the data. This assumes the containing class (for example a view controller) has a property PresetInfo *presetInfo and the XML you posted is in a file presetinfo.xml.
// load the XML into the model
NSString *path = [[NSBundlemainBundle] pathForResource:@"presetinfo"ofType:@"xml"];
self.presetInfo = [[PresetInfoalloc] initWithPath:path];
// verify the model loaded correctly
for (Modality *modality inself.presetInfo.modalities) {
for (Body *body in modality.bodies) {
NSLog(@"Modality Type = %@; Body Part = %@; WW = %d; WL = %d", modality.type, body.part, body.ww, body.wl);
}
}