ios - using NSXMLparser, how do you parse an xml file which has same name tags but in different elements? -
is possible give path expressions in nsxmlparser? have xml file has few same name tags, in different element. there way differentiate between them. here xml:
<schools> <school> <id>335823</id> <name>fairfax high school</name> <student> <id>4195653</id> <name>will turner</name> </student> <student> <id>4195654</id> <name>bruce paltrow</name> </student> <student> <id>4195655</id> <name>santosh gowswami</name> </student> </school> <schools>
i'd create separate school
, student
objects. parser have properties currentschool
, currentstudent
. whenever parser hits <student>
tag, call
self.currentstudent = [[mystudentobject alloc] init];
whenever parser hits </student>
tag, call
self.currentstudent = nil;
then, when hit <name>
tag, can check see if have currentstudent
. if do, name name of student. if there no current student, name name of school.
if (self.currentstudent) { self.currentstudent.name = /*string between <name> tags*/ } else { self.currentschool.name = /*string between <name> tags*/ }
sorry code pieces brief, don't have time type now. if more detail needed, can add more code later.
update
the quickest way me go more detail show code i'm looking for, , put comments explaining code. if there questions on part of this, or if needs explained further, let me know elaborate on , i'll best.
studentxml.h
#import <foundation/foundation.h> @interface studentxml : nsobject @property (nonatomic, strong) nsstring *id; // make sure matches element in xml!! @property (nonatomic, strong) nsstring *name; // make sure matches element in xml!! @end
studentxml.m
#import "studentxml.h" @implementation studentxml @end
schoolxml.h
#import <foundation/foundation.h> #import "studentxml.h" @interface schoolxml : nsobject @property (nonatomic, strong) nsstring *id; // make sure matches element in xml!! @property (nonatomic, strong) nsstring *name; // make sure matches element in xml!! @property (nonatomic, strong) nsmutablearray *studentsarray; // array of studentxml objects @end
schoolxml.m
#import "schoolxml.h" @implementation schoolxml // need overwrite init method array created when new schoolxml object created - (schoolxml *) init; { if (self = [super init]) { self.studentsarray = [[nsmutablearray alloc] init]; return self; } else { nslog(@"error - schoolxml object not initialized in init on schoolxml.m"); return nil; } } @end
schoolsparser.h
#import <foundation/foundation.h> #import "schoolxml.h" #import "studentxml.h" @interface schoolsparser : nsobject { nsmutablestring *currentelementvalue; // hold string between tags until decide put } @property (nonatomic, strong) schoolxml *currentschool; // hold school in process of being filled @property (nonatomic, strong) studentxml *currentstudent; // hold student in process of being filled @property (nonatomic, strong) nsmutablearray *allschools; // final list of data in xml file - (void)parser:(nsxmlparser *)parser didstartelement:(nsstring *)elementname namespaceuri:(nsstring *)namespaceuri qualifiedname:(nsstring *)qualifiedname attributes:(nsdictionary *)attributedict; - (void)parser:(nsxmlparser *)parser foundcharacters:(nsstring *)string; - (void)parser:(nsxmlparser *)parser didendelement:(nsstring *)elementname namespaceuri:(nsstring *)namespaceuri qualifiedname:(nsstring *)qname; @end
schoolsparser.m
#import "schoolsparser.h" @implementation schoolsparser - (void)parser:(nsxmlparser *)parser didstartelement:(nsstring *)elementname namespaceuri:(nsstring *)namespaceuri qualifiedname:(nsstring *)qualifiedname attributes:(nsdictionary *)attributedict // method hit each time parser sees opening tag // elementname string between <> (example "school") { if ([elementname isequaltostring:@"school"]) { self.currentschool = [[schoolxml alloc] init]; } else if ([elementname isequaltostring:@"student"]) { self.currentstudent = [[studentxml alloc] init]; } } - (void)parser:(nsxmlparser *)parser foundcharacters:(nsstring *)string // method hit each time parser sees string between tags // string value between open , close tag (example "fairfax high school") // take string , hold onto until can decide should put { currentelementvalue = [[nsmutablestring alloc] initwithstring:string]; } - (void)parser:(nsxmlparser *)parser didendelement:(nsstring *)elementname namespaceuri:(nsstring *)namespaceuri qualifiedname:(nsstring *)qname // method hit each time parser sees closing tag // elementname string between </> (example "school") // method decide want put currentelementvalue string { if ([elementname isequaltostring:@"student"]) { // put current student studentsarray of currentschool [self.currentschool.studentsarray addobject:self.currentstudent]; // we've finished building student , have put school wanted, clear out currentstudent can reuse next time self.currentstudent = nil; } else if ([elementname isequaltostring:@"school"]) { // put current school allschoolsarray send our view controller [self.allschools addobject:self.currentschool]; // we've finished building school , have put return array, clear out currentschool can reuse next time self.currentschool = nil; } else if ([elementname isequaltostring:@"schools"]) { // reached end of xml document return; } else // either name or id, want put correct currentsomething building { if (self.currentstudent) // there currentstudent, name or id found of student { // since properties of our currentstudent object match elementnames in our xml, parser can automatically fills values in need without doing more // example, take "will turner" in <name> tags in xml , put .name property of our student [self.currentstudent setvalue:currentelementvalue forkey:elementname]; } else // there no student, name or id found of school { // since properties of our currentstudent object match elementnames in our xml, parser can automatically fills values in need without doing more // example, take "fairfax high school" in <name> tags in xml , put .name property of our school [self.currentschool setvalue:currentelementvalue forkey:elementname]; } } // we've put string in currentelementvalue wanted it, clear out currentelementvalue can reuse next time currentelementvalue = nil; } -(void)parser:(nsxmlparser *)parser parseerroroccurred:(nserror *)parseerror { nslog(@"error in schoolsparser.m"); nslog(@"%@",parseerror.description); } @end
uiviewcontroller.m want start parsing (make sure #include
schoolxml, studentxml, , schoolsparser):
- (void) startschoolparser { nsxmlparser *nsxmlparser = [[nsxmlparser alloc] initwithdata:responsedata]; // "responsedata" nsdata object holds xml schoolsparser *parser = [[schoolsparser alloc] init]; [nsxmlparser setdelegate:parser]; if ([nsxmlparser parse]) { // parsing successful nsarray *allschools = parser.allschools; // can loop through allschools , use data how ever want // example, code nslog's data (schoolxml *school in allschools) { nslog(@"school name = %@",school.name); nslog(@"school id = %@",school.id); (studentxml *student in school.studentsarray) { nslog(@"student name = %@",student.name); nslog(@"student id = %@",student.id); } } } else { nslog(@"parsing failed"); } }
Comments
Post a Comment