PDA

View Full Version : NSXMLParser



boboc
01-15-2011, 02:51 PM
Ieri am rezolvat o mica problema legata de un fisier XML si o sa pun aici rezolvarea in caz ca au si altii nevoie.
Pentru a salva datele unui fisier XML de pe un website intr-un array sau dictionar al aplicatiei se creaza un url:


NSURL *url = [NSURL URLWithString: @"adresa web cu XML-ul"];

Apoi se creaza un parser:


NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL: url];

Apoi se incepe analiza XML-ului apeland metoda "parse":


[parser parse];

viewController-ul trebuie sa adopte protocolul NSXMLParser si sa implementeze urmatoarele 3 delegate methods:


// metoda 1
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict


Metoda este trimisa de catre parser catre delegat cand intalneste inceputul unui tag iar aici putem cauta ceea ce ne trebuie,ex tag-ul "Rate":


if([elementName compare: @"Rate"] == NSOrderedSame)
[tempString setString: @""];

tempString este declarat ca NSMUtableString in viewController si la inceputul tag-ului ce il setam @"".


// metoda 2
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

Metoda este trimisa de parser pentru a oferi delegatului toate caracterele elementului curent.


[tempString appendString: string];

trebuie apelata metoda appendString: pentru a adauga caracter cu caracter in tempString deoarece metoda delegat este trimisa de mai multe ori si nu se poate salva direct string-ul.


// metoda 3
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName

Metoda este trimisa de parser catre delegat cand intalneste sfarsitul tag-ului.


if([elementName compare: @"Rate"] == NSOrderedSame)
{
// se face o copie la tempString pentru a avea alta adresa de memorie.
// se adauga string-ul in array apoi se elibereaza memoria,deoarece str a fost creat cu metoda mutableCopy.
NSMutableString *str = [tempString mutableCopy];
[array addObject: str];
str release];
}

StaS
03-28-2011, 03:11 PM
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL: url];
Daca faci chestia asta in main thread , iti blocheaze UI'ul pe durata descarcarii.
Toate descarcarile ar trebui sa se faca asincron.


[elementName compare: @"Rate"] == NSOrderedSame
de ce nu [elementName isEqualToString:@"Rate"]?


NSMutableString *str = [tempString mutableCopy];
un copy simplu e sufucient, se presupune ca nu ai sa modifici stringul dupa ce parsezi XML-ul


Anyway ... e foarte bine ca postezi aceste kestii , poate asa incepe sa se miste treaba cu programarea pt iOS si in Ro.

boboc
04-16-2011, 01:28 PM
@StaS de curiozitate am creat o noua metoda startParser in care am mutat alocarea url-ului si a parser-ului si in care apelez [parser parse].
Am creat si un NSAutoreleasePool iar in viewDidLoad am apelat:


[self performSelectorInBackground: @selector(startParser) withObject: nil];

Am verificat cu instruments si exista memory leaks,si imi indica 97% din leaks spre:


NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL: url];

Ai idee de ce?

StaS
04-16-2011, 04:23 PM
Eu de obicei fac doar downloadul intr'un thread separat , parsingul il fac in main.

boboc
04-16-2011, 04:28 PM
Inteleg,probabil ca parsingul nu dureaza mult daca XML-ul este downloadat.
La mine am vazut care era si problema cu leak-ul.
In didStartElement: eu aveam asa:


tempKey = [attributeDict objectForKey: @"currency"];

si trebuia asa:


self.tempKey = [attributeDict objectForKey: @"currency"];

daca nu folosesc self. nu se apeleaza si setter-ul deci prin urmare nici retain.
Acum vad ca Instruments arata totul ok.

dorinpaunescu
07-12-2011, 12:18 PM
Salut ! Imi poate cineva sugera o modalitate de a prelucra un fisier XML in iOS asa cum se poate de exemplu in java cu DOM ...
SAX permite modificarea ?