0

I've been stuck a little on this problem. Here is the situation : I'm parsing an xml file with positions, I parse it well, thing is I want to put the different elements into an NSDictionary (one NSDictionary for each position) and those NSDictionary into an NSMutableArray.

- (void) traverseElement:(TBXMLElement *)element {

NSMutableDictionary *position = [[NSMutableDictionary alloc]init];
NSArray *keys = [NSArray arrayWithObjects:@"cab",@"idagencedepart", @"idagencefinale",@"iddestinataire",@"idexpediteur",@"idtransporteurreexpedition",@"departement",@"message1", nil];
[position dictionaryWithValuesForKeys:keys];

do {

    TBXMLAttribute * attribute = element->firstAttribute;


    // if attribute is valid

    while (attribute) {


        if ([[TBXML elementName:element] isEqualToString:@"referencecolis"]) {
            [position setObject:[TBXML textForElement:element] forKey:@"cab"];
            NSLog(@"cab : %@",[TBXML textForElement:element]);
            };

        if ([[TBXML elementName:element] isEqualToString:@"idagencedepart"]) {
            [position setObject:[TBXML textForElement:element] forKey:@"idagencedepart"];
            NSLog(@"idagencedepart : %@",[TBXML textForElement:element]);

        };

        [modulectrlcle addObject:position];

  attribute = attribute->next;



    }

    if (element->firstChild)

        [self traverseElement:element->firstChild];



} while ((element = element->nextSibling));

}

}

Here is my code. It parses well, but my NSMutableArray (modulectrle) is filled with weird NSDictionaries...

Romain
  • 151
  • 1
  • 12
  • Can you also put a link to XML somewhere so we can check if that's valid XML file ? Usually with parsers the issues is that XML is not valid. – Grzegorz Krukowski Sep 16 '13 at 14:44
  • It's not a problem of the parser, when I NSLog the result of the parsing it's fine, my problem is when I fill the data in the NSDictionary. Where and when should I instanciate the NSDictionary and add it in the NSMutableArray ? When I NSlog the NSDictionary, it's either nil or it's the same hundreds of times – Romain Sep 16 '13 at 14:52
  • What is modulectrlcle ? You are adding position to modulectrlcle. And in next loop cycle you are adding again values to the same NSDictonary and again add it to an array... – Grzegorz Krukowski Sep 16 '13 at 14:53
  • Try doing NSMutableDictionary *position = [[NSMutableDictionary alloc]init]; inside while (attribute) { [[NSMutableDictionary alloc]init]; } – Grzegorz Krukowski Sep 16 '13 at 14:54
  • "modulectrlcle" is the NSMutableArray that must be filled with the NSDictionaries – Romain Sep 16 '13 at 14:56
  • When I put the instanciation of the NSMutableDictionary inside the while loop, it only adds a few "referencecolis" and tons of empty NSMutableDictionary – Romain Sep 16 '13 at 14:59
  • Check my answer below - I edited to your comment – Grzegorz Krukowski Sep 16 '13 at 15:09

1 Answers1

-1

Allocate NSDictonary inside while loop:

do {
     TBXMLAttribute * attribute = element->firstAttribute;
     while (attribute) {
        NSMutableDictionary *position = [[NSMutableDictionary alloc]init];

        BOOL foundElement = NO;
        if ([[TBXML elementName:element] isEqualToString:@"referencecolis"]) {
            [position setObject:[TBXML textForElement:element] forKey:@"cab"];
            NSLog(@"cab : %@",[TBXML textForElement:element]);
            foundElement = YES;
        };

        if ([[TBXML elementName:element] isEqualToString:@"idagencedepart"]) {
            [position setObject:[TBXML textForElement:element] forKey:@"idagencedepart"];
            NSLog(@"idagencedepart : %@",[TBXML textForElement:element]);
            foundElement = YES;
        };

        if(foundElement) //avoid adding empty NSDictonaries
        {
             [modulectrlcle addObject:position];
        }

        attribute = attribute->next;
    }

    if (element->firstChild)
        [self traverseElement:element->firstChild];

} while ((element = element->nextSibling));

Otherwise you add same NSDictonary all over again to an array and you push all elements into same dictionary and as a result you get array with a same dictionary several times.

Grzegorz Krukowski
  • 18,081
  • 5
  • 50
  • 71
  • `NSDictionary` has a `count` method, no need to waste CPU cycles by create a temporary `NSArray` to get the number of elements. – JustSid Sep 16 '13 at 15:29
  • @JustSid it's not optimized for sure - best solution will be to create NSMutableDictonary outside and clean it instead of allocating each time - I will update my answer after I know it helped. – Grzegorz Krukowski Sep 16 '13 at 15:32
  • Check my update for some memory / performance optimizations to allocate object only once and reusing it - also using BOOL flag instead of calculating count each time as @JustSid suggested. – Grzegorz Krukowski Sep 16 '13 at 15:35
  • Thanks, my last question is that I could have several "referenceposition" and I want to add it to the "cab" key of the NSMutableDictionary. How do you iterate through an array at the key "cab" of the NSMutableDictionary ? What I do is I "setObject:cab forKey:@"cab"", where cab is the array filled with the elements found at "referenceposition" in the xml – Romain Sep 16 '13 at 15:45
  • @GrzegorzKrukowski I didn't suggest a bool flag at all, I suggested to use the `count` method provided by `NSDictionary`. – JustSid Sep 16 '13 at 20:25
  • 1
    Also, you just "optimized" the code so that it suffers from the same error as the code in the question. – JustSid Sep 16 '13 at 20:30
  • @JustSid not really - please notice: "[position removeAllObjects];" but anyways I pasted full code from question to clarify. – Grzegorz Krukowski Sep 17 '13 at 07:49
  • 1
    @GrzegorzKrukowski Yes, really. You mutate one and the same dictionary and add it multiple times to an array (which doesn't make a copy of the data). You end up with one dictionary multiple times in the same array. – JustSid Sep 17 '13 at 09:21
  • @JustSid haha you're right... Stupid me :D Fixed it. The way to optimize it will be to convert if / else into some loop and create dictionary only when necessary if any of key were found. But I will let him do that. :) – Grzegorz Krukowski Sep 17 '13 at 09:45