0

i'm looking for a advise. I want to parse an XML file with NSXMLParser, and i wonder what i should do with tags and parameters. Fo example i have:

<template>
    <template name="default" layout="absolute">
        <image tmpl="topbanner"/>
        <list tmpl="list">
            <font tmpl="listfont"/>
            <item target="target1">
                <text>Target1</text>
            </item>
            <item target="target2">
                <text>Target2</text>
            </item>
            <item target="target3">
                <text>Target3</text>
            </item>
                .
                .
                .

And later i want to create an objects base on this information. So - where should i store retrieve information from parser? In method:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{
    element = [NSMutableString string];
}

I see that i can simply recieve atributes ang tags, but should I in this point write it in NSMutableArray or NSDictionary?

I've read NSXMLParser how to pass the NSMutableDictionary to a NSMutableArray But is it the best way?

Community
  • 1
  • 1
Jakub
  • 13,712
  • 17
  • 82
  • 139

2 Answers2

1

If you know that a <list> element contains an array of subelements, you'll probably want to create an array or dictionary at the start of that block:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{
    if ([elementName isEqualToString:@"list"]) {
        self.list = [NSMutableDictionary dictionary];
        self.listName = [attributeDict objectForKey:@"tmpl"]
    }
    else if ([elementName isEqualToString:@"item"]) {
        self.itemKey = [attributeDict objectForKey:@"target"];
    }
    else if ([elementName isEqualToString:@"text"]) {
        self.data = [NSMutableString string];
    }
    else if ([elementName isEqualToString:@"font"]) {
        self.font = [attributeDict objectForKey:@"tmpl"];
    }
}

Then you can add the simple <item> elements in your -parser:didEndElement:... method:

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if (elementName isEqualToString:@"text") {
        // no action needed here -- data already contains the text
    }
    else if (elementName isEqualToString:@"item"]) {
        [self.list setObject:[self.data copy] forKey:self.itemKey;
        self.itemKey = nil;
    }
    else if ([elementName isEqualToString:@"list"]) {
        // do something appropriate with the list
        [self.template setObject:self.items forKey:self.listName];
        self.listName = nil;
        self.list = nil;
    }
}

This all presumes that you've got properties for font, data, itemKey, and so on... basically whatever you need to remember all the state you need until you can create the related object. Once you have the data you need, usually in the didEnd method, create the object, store it somewhere, and clear out the saved data.

This isn't the only approach to parsing the data. For example, you might want to go with a stack-based approach instead. But the idea illustrated above is probably the easiest to understand, and if the data isn't too complicated it's not hard to manage.

Caleb
  • 124,013
  • 19
  • 183
  • 272
0

To get what's inside the tag use:

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [element appendString:string];
}

Then check in :

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {

To get the attributes :

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {

    if ([elementName isEqualToString:@"image"]) {
        NSString *imageName = [attributeDict objectForKey:@"tmpl"];
    }

}

TegRa
  • 519
  • 3
  • 10
  • Sorry, but that no answering my question. I know all of it and I said that in my post. – Jakub Apr 10 '12 at 11:09
  • I don't really understand what you mean here then? In didEndElement you set [myDictionary setObject:element forKey:elementName] and when you reach the end tag where you want to create the object you just transform the dictionary into the object. – TegRa Apr 10 '12 at 14:06