T#042 – Come utilizzare XML nelle nostre applicazioni iPhone (SDK)
Eccoci con un nuovo tutorial dedicato alla programmazione per iPhone. Oggi vedremo come integrare nelle nostre applicazioni iPhone (e iPad) una tecnologia molto utilizzata, specialmente in ambito web: stiamo parlando di XML. Vedremo, quindi, come leggere un file XML, da cui preleveremo delle informazioni che abbiamo salvato. Questa operazione verrà eseguita in locale (ovvero il file xml sarà all’interno del nostro progetto), ma nulla ci vieta di avere il file caricato su un server web da cui accediamo tramite la nostra applicazione.
1. Cosa è XML?
XML è un metalinguaggio (in quanto non è un linguaggio di programmazione vero e proprio) di markup, ovvero un linguaggio che consente di estendere o controllare il comportamento di altri linguaggi. Il linguaggio di markup più famoso è sicuramente l’HTML, che ha molte analogie con l’XML.
XML è l’acronimo di eXtensible Markup Language, da cui possiamo capire la caratteristica fondamentale di questo linguaggio: ci permette di creare tag personalizzati, in base alle nostre esigenze.
Sarà più semplice comprendere come funziona questo linguaggio mediante un esempio:

La prima riga definisce la versione di XML in uso e la codifica utilizzata (secondo le norme ISO). Dalla seconda riga in poi, invece, troviamo dei tag personalizzati, che vanno a modellare i dati a nostro piacimento.
Possiamo vedere come abbiamo definito il tag generale “studenti”, che viene iniziato alla seconda riga e concluso all’ultima. Nel mezzo troviamo, invece, altri tag, che riportano le informazioni che vogliamo memorizzare, per poi utilizzarle a nostro piacimento.
Ci sono alcune piccole regole da rispettare nella sruttura XML:
- I tag non possono iniziare con numeri o caratteri speciali e non possono contenere spazi.
Corretti:, ,
Errati: <&soldi>, <12peso>, - I tag devono essere bilanciati (ogni tag aperto deve essere chiuso)
Corretto:Andrea
Errato:Andrea - I tag non devono contenere errori di annidamento.
Ecco alcuni esempi errati:

- Si possono inserire degli attributi all’interno dei tag; la struttura sarà quindi la segente:
Valore
I nostri elementi, quindi, potranno essere scritti anche nella seguente maniera:

Questa struttura è del tutto uguale a quella precedente. Notate che in questo caso non abbiamo usato il tag di chiusura, ma abbiamo inserito “/” all’interno del tag stesso proprio per indicare che quel tag non ha elemento di chiusura. Quello che cambierà sarà solamente il modo di leggere i valori via codice.
2. XML nell’SDK di iPhone
Per ora abbiamo fatto una panoramica su XML in generale, presentando gli aspetti fondamentali di tale linguaggio. Ma come possiamo integrarlo con le nostre applicazioni? L’oggetto che si occupa di recuperare i dati da un file XML viene detto parser.
Esistono vari tipi di parser (diversi per linguaggi e tecnologie), noi andremo ad utilizzare SAX. La caratteristica di questo parser sta nel fatto che processa i documenti linea per linea: dati a cui si è acceduto in precedenza non possono essere riletti senza la rielaborazione dell’intero documento. Può essere uno svantaggio, ma è l’unico parser disponibile nell’SDK per iPhone!!
3. Creiamo un nuovo progetto
Aprimo Xcode e selezioniamo “File -> New Project”. Nel menù che ci appare selezioniamo “View-Based Application”, clicchiamo su “Choose…”, immettiamo come nome “xmlTutorial” e facciamo clic su “Save”. Abbiamo così creato il nostro nuovo progetto.

In questo tutorial utilizzeremo la vista e la classe che XCode ha già definito per noi. Prima di definire l’aspetto grafico, però, dichiariamo i componenti che ci servono. Apriamo il file “xmlTutorialViewController.h” e modifichiamolo così:
1 2 3 4 5 6 7 8 9 10 11 | #import <UIKit/UIKit.h> @interface xmlTutorialViewController : UIViewController { IBOutlet UITextView *textArea; NSString *path; } -(IBAction)avviaParsing; @end |
Abbiamo dichiarato una UITextView (riga 4) in cui inseriremo i dati letti dal file xml, un’azione (riga 6), che andrà collegata ad un bottone (tale azione farà iniziare il processo di parsing) e una stringa che conterrà il percorso del file xml.
Salviamo il file (“File -> Save”).
4. Creiamo la struttura grafica
Apriamo ora il file “xmlTutorialViewControlle.xib”, che avvierà Interface Builder. Nella nostra applicazione, inseriamo un bottone e una TextView, di dimensioni abbastanza ampie, in quanto dovrà contenere tutti i valori letti dal nostro file xml. Dovreste ottenere un risultato come questo:

Ora, selezionando l’ UITextView, entriamo in “Attributes Inspector”, togliamo quindi la spunta da “Editable”:

questo perchè non vogliamo che l’utente possa modificare i valori presenti nella TextView (ovvero deve essere di sola lettura).
Dal pannello dei documenti (“Tools -> Reveal in Document Window”) selezioniamo “File’s Owner”, ovvero la classe che gestisce il nostro file.

Apriamo il “Connections Inspector” e qui, potremo vedere alcuni elementi, compresi i due che abbiamo definito noi all’inizio del nostro progetto. Colleghiamo “textArea” con la UITextView presente nella nostra vista, e l’azione “avviaParsing” con il bottone: quando apparirà il menù con tutte le azioni disponibili, selezioniamo “Touch Up Inside”. Se avrete eseguito tutto correttamente avrete un pannello che si presenterà così:

Abbiamo terminato la creazione della struttura grafica. Possiamo salvare tutto e chiudere Interface Builder.
5. Scriviamo il codice necessario
Prima di procedere con il codice necessario, dobbiamo inserire all’interno del progetto il file xml con i nostri dati, semplicemente trascinandolo all’interno di “Resources” in “Groups & Files”. Se avete capito la struttura di tali file, potete creare uno a vostro piacimento (fate attenzione a salvarlo con estensione .xml), altrimenti potete utilizzare nel vostro progetto il nostro file di esempio.
Apriamo ora il file “xmlTutorialViewController.m” e definiamo il seguente metodo:
1 2 3 4 5 6 7 | // Metodo eseguito all'avvio della vista - (void)viewDidLoad { [super viewDidLoad]; // definiamo il percorso del file xml NSString *pathProgetto = [[NSBundle mainBundle] bundlePath]; path = [[NSString alloc] initWithString:[pathProgetto stringByAppendingPathComponent:@"dati.xml"]]; } |
Questo metodo viene eseguito all’avvio della vista e ci permette di definire dei comportamenti che devono essere eseguiti prima di ogni altra cosa. Con le due istruzioni che vedete nelle righe 5 e 6, definiamo il percorso del nostro file “dati.xml”: esso viene cercato all’interno della cartella del nostro progetto. Queste istruzioni sono molto importanti, in quanto non viene definito un percorso assoluto (soluzione sempre sconsigliabile e spesso errata), ma viene definito il percorso effettivo in cui si trova il file.
Dobbiamo ora definire l’azione che viene eseguita quando premiamo sul pulsante. Ecco il codice da inserire:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | -(IBAction)avviaParsing{ //Bisogna convertire il file in una NSURL altrimenti non funziona NSURL *xmlURL = [NSURL fileURLWithPath:path]; // Creiamo il parser NSXMLParser *parser = [[ NSXMLParser alloc] initWithContentsOfURL:xmlURL]; // Il delegato del parser e' la classe stessa (self) [parser setDelegate:self]; //Effettuiamo il parser BOOL success = [parser parse]; //controlliamo come è andata l'operazione if(success == YES){ //parsing corretto } else { //c'è stato qualche errore... } // Rilasciamo l'oggetto NSXMLParser [parser release]; } |
Le prime due istruzioni (righe 3 e 5) ci permettono di definire il parser, partendo dal percorso del nostro file. Alla riga 9 avviamo il processo di parsing, salvando il risultato in una variabile booleana: se essa vale YES la conversione si è conclusa senza errori, altrimenti c’è stato un errore (che potrebbe essere dovuto ad errori nella struttura del file xml oppure ad errori di scrittura del codice).
Come potete vedere non si tratta di codice complesso, sono poche istruzioni che dovrebbero risultarvi chiare.
La parte che viene ora è quella che si occupa di leggere i dati dal file xml. Iniziamo inserendo questo metodo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict { if ([elementName isEqualToString:@"studenti"]){ [textArea setText:[[NSString alloc] initWithFormat:@"%@\nInizio studenti",textArea.text]]; NSLog(@"ok"); } else if([elementName isEqualToString:@"studente"]){ [textArea setText:[[NSString alloc] initWithFormat:@"%@\nNuovo studente",textArea.text]]; } else if([elementName isEqualToString:@"matricola"]) { [textArea setText:[[NSString alloc] initWithFormat:@"%@\nMatricola: ",textArea.text]]; } else if([elementName isEqualToString:@"cognome"]) { [textArea setText:[[NSString alloc] initWithFormat:@"%@\nCognome: ",textArea.text]]; } else if([elementName isEqualToString:@"nome"]) { [textArea setText:[[NSString alloc] initWithFormat:@"%@\nNome: ",textArea.text]]; } } |
Come potete osservare, vi sono una serie di controlli if, che vanno a testare l’elemento corrente, per riconoscerlo e per scrivere una stringa adeguata nella textArea che abbiamo predisposto. Questo processo è possibile perchè conosciamo a priori la struttura del file xml: questo è quasi sempre vero, in quanto sarebbe quasi impossibile leggere un file xml di cui non conosciamo la struttura interna.
Il metodo viene, ovviamente, richiamato ogni volta che il parser incontra un nuovo elemento, cioè l’apertura di un tag.
Per completare il nostro programma mancano solo due metodi:
1 2 3 4 5 6 7 8 | - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { [textArea setText:[[NSString alloc] initWithFormat:@"%@%@",textArea.text,string]]; } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { [textArea setText:[[NSString alloc] initWithFormat:@"%@\nFine elemento: %@",textArea.text,elementName]]; } |
Il primo viene richiamato quando il parser incontra un valore racchiuso tra due tag (l’informazione vera e propria). Nel nostro caso ci limitiamo a inserirla nella textArea, però potreste fare delle operazioni più o meno complesse sulle informazioni che leggete dal file.
L’ultimo metodo, invece, viene richiamato quando il parser incontra un tag di chiusura. Anche in questo caso l’unica azione che faremo sarà quella di inserire una stringa nella textArea.
Possiamo finalmente cliccare su “Build and Go!” e testare la nostra applicazione funzionante!


















veramente utile!
Se possibile… potete scrivere qualche tutorial sul parsing di dati xml su uno stream socket? Avrei neceesità di leggere dei dati da un server in xml (non in un file ma in uno stream) e restituire i dati letti in una tabella sull’iphone….