0
votes

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?

2

2 Answers

1
votes

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.

0
votes

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"];
    }

}