Estou tentando analisar um XML que estou recebendo de um serviço da web com um NSXMLParserDelegate
. o NSObject
Eu quero colocar os dados (eu vou chamá -los MyObject
) tem @property
s que não são NSString
s (existem alguns NSDate
s, alguns NSNumber
s, e talvez em algum momento no futuro, alguns primitivos).
Como o XML é um grande string, estou recebendo erros e travamentos quando tento apenas colocar os valores diretamente do XML em minhas propriedades (estou usando [myObject setValue:currentElementValue forKey:elementName];
no meu parser:didEndElement:...
, que normalmente funciona bem - quando key
é um NSString
). Eu realmente não esperava que isso funcionasse, mas achei que valia a pena tentar.
A coisa mais fácil de fazer é apenas codificar tudo, então, se eu tiver um '@property (não atômico, forte) nsnumber *idade;' no meu objeto, quando eu encontro o <age>25</age>
parte do meu XML, eu faço MyObject.age = [NSNumber numberWithInt:[currentElementValue intValue]];
. O problema é muito rígido - eu gostaria que esse código fosse mais dinâmico do que isso. Não quero saber quais todas as propriedades do meu objeto estão com antecedência.
Eu também tentei verificar o que o class
da propriedade está, depois fazendo alguma conversão antes de entrar em um valor (então algo como [myObject setValue:[NSNumber numberWithInt:[currentElementValue intValue] forKey:elementName];
se a propriedade isKindOfClass:[NSNumber class]]
. O problema disso é que é a primeira vez que a propriedade é usada, então é nil
, e, portanto, não tem uma classe. Portanto, essa abordagem também não funciona.
Estou fazendo isso completamente errado? Parece que deve ser bastante típico obter dados de um XML e colocá-los em nãoNSString
Variáveis, mas não consigo fazer com que funcione.
Se alguém precisar ver mais código para entender melhor como eu está configurado ou o que eu já tentei, me avise.
EDIT: Eu cheguei a um exemplo rápido do que estou tentando fazer. Suponha que eu tenha o seguinte XML:
<Object>
<ITEM_NUMBER>4</ITEM_NUMBER>
<IS_AWESOME>YES</IS_AWESOME>
<AWESOMENESS>9000.1</AWESOMENESS>
</Object>
que eu quero analisar uma instância de MyObject
(um NSObject
subclasse)
@interface MyObject: NSObject
@property (nonatomic, assign) int ITEM_NUMBER;
@property (nonatomic, assign) BOOL IS_AWESOME;
@property (nonatomic, assign) float AWESOMENESS;
@end
E um segundo xml
<OtherObject>
<PRICE>4.99</PRICE>
<QUANTITY>5</QUANTITY>
<FOR_RESALE>NO</FOR_RESALE>
</OtherObject>
Isso entrará em um exemplo de OtherObject
(também NSObject
subclasse)
@interface OtherObject: NSObject
@property (nonatomic, assign) int QUANTITY;
@property (nonatomic, assign) BOOL FOR_RESALE;
@property (nonatomic, assign) float PRICE;
@end
Eu quero criar um analisador de "modelo" (que tem @property (nonatomic, strong) NSObject *instance;
e depois NSMutableString *currentElementValue
como um ivar)
...
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[currentElementValue setString:string];
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([[self.instance valueForKey:elementName] isKindOfClass:int])
{
[self.instance setValue:[currentElementValue intValue] forKey:elementName];
}
else if ([[self.instance valueForKey:elementName] isKindOfClass:float])
{
[self.instance setValue:[currentElementValue floatValue] forKey:elementName];
}
else if ([[self.instance valueForKey:elementName] isKindOfClass:BOOL])
{
[self.instance setValue:[currentElementValue boolValue] forKey:elementName];
}
else if ...
}
...
Então, apenas subclasse esse analisador de "modelo" para cada um dos meus diferentes xmls e substitui o init
método para que
self.instance = [[MyObject alloc] init];
ou
self.instance = [[OtherObject alloc] init];
como apropriado. Eu tenho muitos serviços da web que chamo de que vou receber XML de maneira semelhante, então apenas ter que alterar 1 linha nos analisadores para cada um é algo que é muito desejável. Ter todo o restante do código do analisador em uma única classe "modelo" facilitará muito a manutenção, a leitura e a depuração do código.
Obviamente, o problema que estou tendo é isKindOfClass
não aceita int
, float
, ou BOOL
como entradas. Existe algo semelhante que eu possa usar?