Типы данных для использования с NSXMLParser - PullRequest
0 голосов
/ 14 апреля 2009

Я использую NSXMLParser для анализа XML-данных с удаленного сервера. Я следовал руководству, чтобы начать работу, и все в порядке для любых (NSString *) членов, которые у меня есть в моих объектах, которые я создаю. У меня также есть целые числа, которые мне нужно установить из данных XML, например:

<root>
    <child>
        <name> Hello </name>
        <number> 123 </number>
    </child>
    <child>
        <name> World</name>
        <number> 456 </number>
    </child>
</root>

В этом случае я бы создал два "дочерних" объекта. Я использую:

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
      namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    ...
    [aChild setValue:currentElementValue forKey:elementName];
    ...
}

Делегат для установки значений. Вот где я добираюсь до своей проблемы. Элемент "NSString * name" устанавливается нормально каждый раз, однако если я использую NSInteger, то всякий раз, когда я пытаюсь установить "число", я получаю EXC_BAD_ACCESS. Поэтому я попытался использовать вместо него "int". Но теперь я не могу использовать программирование значения ключа и мне нужно искать узел вручную:

if([elementName isEqualToString:@"number"]) {
    aChild.number = [currentElementValue intValue]
}

Это нормально, я могу с этим справиться, потому что я знаю, какие узлы я получу, но становится хуже. Когда currentElementValue является «NSMutableString *» в соответствии с руководством, оно не возвращает правильное целое число, даже если строка является правильной. Например:

    NSLog(@"NSMutableString Value: %@, and intValue %d\n", currentElementValue, [currentElementValue intValue]); 
// Value will be 123 but intValue will be 0

Итак, я сделал currentElementValue NSString вместо NSMutableString, и я могу получить правильное intValue. Но я читал в Интернете, что это NSMutableString, потому что:

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

Делегат, используемый для установки значения , может встречаться более одного раза, но обычно это не так. Итак, мой вопрос: кто-нибудь знает, что я делаю неправильно? Это кажется довольно тривиальным случаем для NSXMLParser, поэтому я уверен, что это то, что я неправильно понимаю.

Ответы [ 3 ]

2 голосов
/ 14 апреля 2009
  1. intValue должны работать одинаково NSString и NSMutableString. Вы уверены, что значением было «123», а не «\ n123» (\ n означает символ новой строки), если строка не начинается с десятичного числа, intValue вернет 0.

  2. Правильно ли вы очищаете изменяемую строку в parser:didStartElement:? Если вы выполняете очистку только в parser:didEndElement:, тогда parser:foundCharacters: также будет собирать символы из родительского элемента. Который в этом случае префикс вашей строки с новой строки, и intValue вернет 0.

  3. Вы правы в том, что parser:foundCharacters: можно вызывать несколько раз для одного элемента.

2 голосов
/ 14 апреля 2009

Я не знаю, где ваш код не работает, но вот правильный способ справиться с этим:

NSMutableString *buffer = [[NSMutableString alloc] init];

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
    [buffer setString:@""];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    if([elementName isEqualToString:@"number"]) {
        [aChild setNumber:[buffer intValue]];
        [buffer setString:@""];
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [buffer appendString:string];
}
1 голос
/ 16 апреля 2009

Здесь происходит пара вещей.

Во-первых, у вас есть очевидные пробелы в ваших символьных данных XML, например,

        <number> 456 </number>

Тебе действительно нужно убрать этот пробел. Вероятно, именно поэтому возвращаемое значение [NSString intValue] неверно. Если вы можете удалить его у источника, отлично. Если нет, вы можете удалить его на принимающей стороне, выполнив:

currentElementValue = [currentElementValue stringByTrimmingCharactersInSet:
    [NSCharacterSet whitespaceAndNewlineCharacterSet]];

Причина, по которой вы не можете использовать ключ / значение, заключается в том, что вы не можете сохранить значение NSInteger в NSMutableDictionary. И ключи, и значения в словаре должны происходить от NSObject, а NSInteger (здесь я догадываюсь) просто безопасная для платформы typedef из int. Так что вместо этого вы должны использовать NSNumber:

NSNumber *theInt = [NSNumber numberWithInt:[currentElementValue intValue]];
[aChild setObject:theInt forKey:elementName];
...