[Objective-c] Application iPhone qui parse un fichier XML
juillet 28, 2011
Dans cet article nous allons voir comment parser un fichier Xml et récupérer les informations contenues. Dans un second article, on affichera ces infos dans un tableView. Merci à Medhi.N pour l’idée de ce tutorial! Allez C’est parti…
I) Introduction
Nous allons donc créer une application permettant de parser un fichier xml ce trouvant sur le net. Par exemple un fichier contenant des contacts.
1 2 3 4 5 6 7 8 9 | <contacts> <Contact> <nom>Smith</nom> <prenom>Joe</prenom> <tel>321-123-4567</tel> <email>joe@smith.com</email> </Contact> <!--...--> </contacts> |
Vous pouvez retrouver un exemple de fichier à cette adresse : http://www.jkraft.fr/testXml.xml
II) Contact
Commencons par créer un projet de type « Navigation-Based ». Notre fichier XML contenant des contacts nous allons créer une classe qui va gérer ces données. Ajouter une NSObject subclass, nommer la Contact.m et copiez ce code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //Contact.h #import <Foundation/Foundation.h> @interface Contact : NSObject { NSString *prenom; NSString *nom; NSString *tel; NSString *email; } @property (nonatomic, retain) NSString *prenom; @property (nonatomic, retain) NSString *nom; @property (nonatomic, retain) NSString *tel; @property (nonatomic, retain) NSString *email; @end |
1 2 3 4 5 6 7 8 9 10 11 | //Contact.m #import "Contact.h" @implementation Contact @synthesize prenom; @synthesize nom; @synthesize tel; @synthesize email; @end |
Il n’y a rien de compliqué ici, on a crée une classe contact contenant 4 champs.
III) Parseur XML
Maintenant on va s’attaquer au parseur XML. C’est cette classe qui va ouvrir et fermer les balises et récupérer les données. Ajouter une 2eme classe de type NSObject du nom de XMLToObjectParser (par : Andrew).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //XMLToObjectParser.h #import <Foundation/Foundation.h> @interface XMLToObjectParser : NSObject <NSXMLParserDelegate> { NSString *className; NSMutableArray *items; NSObject *item; // stands for any class NSString *currentNodeName; NSMutableString *currentNodeContent; } - (NSArray *)items; - (id)parseXMLAtURL:(NSURL *)url toObject:(NSString *)aClassName parseError:(NSError **)error; @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | //XMLToObjectParser.m #import "XMLToObjectParser.h" @implementation XMLToObjectParser - (NSArray *)items { return items; } - (id)parseXMLAtURL:(NSURL *)url toObject:(NSString *)aClassName parseError:(NSError **)error { [items release]; items = [[NSMutableArray alloc] init]; className = aClassName; NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url]; [parser setDelegate:self]; [parser parse]; if([parser parserError] && error) { *error = [parser parserError]; } [parser release]; return self; } - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { NSLog(@"Open tag: %@", elementName); if([elementName isEqualToString:className]) { // create an instance of a class on run-time item = [[NSClassFromString(className) alloc] init]; } else { currentNodeName = [elementName copy]; currentNodeContent = [[NSMutableString alloc] init]; } } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { NSLog(@"Close tag: %@", elementName); if([elementName isEqualToString:className]) { [items addObject:item]; [item release]; item = nil; } else if([elementName isEqualToString:currentNodeName]) { // use key-value coding [item setValue:currentNodeContent forKey:elementName]; [currentNodeContent release]; currentNodeContent = nil; [currentNodeName release]; currentNodeName = nil; } } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { [currentNodeContent appendString:string]; } - (void)dealloc { [items release]; [super dealloc]; } @end |
Cette classe va parcourir le xml et s’il trouve une balise portant le nom de la classe Contact, y copier les informations et retourner un objet de ce type.
IV) Code principal
Il ne reste plus qu’a faire fonctionner tout ca ensemble. Surtout n’oubliez les imports des 2 fichiers, XMLToObjectParser.h et Contact.h. Dans la classe principale de votre application,normalement RootViewController.m , il suffit d’ajouter ceci (dans mon cas dans le viewDidLoad).
1 2 3 4 5 6 7 8 9 10 11 12 | - (void)viewDidLoad { NSURL *url = [NSURL URLWithString: @"http://www.jkraft.fr/testXml.xml"]; XMLToObjectParser *myParser = [[XMLToObjectParser alloc] parseXMLAtURL:url toObject:@"Contact" parseError:nil]; for(int i = 0; i < [[myParser items] count]; i++) { NSLog(@"Prénom: %@", [(Contact *)[[myParser items] objectAtIndex:i] prenom]); } [super viewDidLoad]; } |
Une petite compilation et lors de l’exécution vous verrez apparaître dans la console toutes les ouvertures et fermetures des balises XML lors du parsage du fichier. Puis à la fin les prénoms lors du parcours de l’objet retourné.
Vous pouvez retrouver les fichiers sources ici : https://github.com/Jekar/jkraft-tuto
Catégorie(s): Développement, Iphone, Objective-C, Tutorial | Comments (25)