Я пытаюсь проанализировать XML, который я получаю из веб-службы с помощью NSXMLParserDelegate
. NSObject
Я хочу поместить данные (я просто позвоню MyObject
) имеет @property
s, которые не являются NSString
s (есть некоторые NSDate
s, некоторые NSNumber
и, возможно, в какой-то момент в будущем некоторые примитивы).Динамический анализ XML в переменных, отличных от NSString
Поскольку XML - это большая строка, я получаю ошибки и сбои, когда пытаюсь просто прямо поместить значения из XML в свои свойства (я использую [myObject setValue:currentElementValue forKey:elementName];
в своем parser:didEndElement:...
, который обычно работает нормально - когда key
- NSString
). Я действительно не ожидал, что это сработает, но я подумал, что это стоит того.
Проще всего сделать это всего лишь hardcode, поэтому, если у меня есть "@property (nonatomic, strong) NSNumber * age; ' на моем объекте, когда я нахожу <age>25</age>
часть моего XML, я делаю MyObject.age = [NSNumber numberWithInt:[currentElementValue intValue]];
. Проблема с этим в том, что она очень жесткая - я бы хотел, чтобы этот код был более динамичным. Я не хочу знать, что все свойства моего объекта опережают время.
Я также попытался проверить, что class
в собственности, а затем делать некоторые преобразования, прежде чем ввести значение (так что-то вроде [myObject setValue:[NSNumber numberWithInt:[currentElementValue intValue] forKey:elementName];
, если свойство isKindOfClass:[NSNumber class]]
. Проблема в том, что это первый раз, когда свойство так что это nil
, и поэтому у него нет класса. Поэтому такой подход тоже не работает.
Я делаю это совершенно неправильно? Кажется, должно быть довольно типично получать данные из XML и помещать его в переменные не NSString
, но я не могу заставить его работать.
Если кому-то нужно см. больше кода, чтобы лучше понять, как я настроен или что я уже пробовал, дайте мне знать.
EDIT: Я придумал простой пример того, что я пытаюсь сделать.Предположим, у меня есть следующий XML:
<Object>
<ITEM_NUMBER>4</ITEM_NUMBER>
<IS_AWESOME>YES</IS_AWESOME>
<AWESOMENESS>9000.1</AWESOMENESS>
</Object>
, что я хочу, чтобы разобрать в экземпляр MyObject
(NSObject
подкласса)
@interface MyObject: NSObject
@property (nonatomic, assign) int ITEM_NUMBER;
@property (nonatomic, assign) BOOL IS_AWESOME;
@property (nonatomic, assign) float AWESOMENESS;
@end
И второй XML
<OtherObject>
<PRICE>4.99</PRICE>
<QUANTITY>5</QUANTITY>
<FOR_RESALE>NO</FOR_RESALE>
</OtherObject>
, который будет идти в OtherObject
(также NSObject
)
@interface OtherObject: NSObject
@property (nonatomic, assign) int QUANTITY;
@property (nonatomic, assign) BOOL FOR_RESALE;
@property (nonatomic, assign) float PRICE;
@end
Я хочу, чтобы создать «шаблон» синтаксический анализатор (который имеет @property (nonatomic, strong) NSObject *instance;
, а затем NSMutableString *currentElementValue
как Ивар)
...
- (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 ...
}
...
Тогда я просто подкласс, что «шаблон» синтаксический анализатор для каждого из моих различных XMLs и перезаписать метод init
так, что
self.instance = [[MyObject alloc] init];
или
self.instance = [[OtherObject alloc] init];
в зависимости от ситуации. У меня есть много веб-сервисов, которые я называю, что я получаю подобный структурированный XML-код, поэтому только изменение одной строки в синтаксических анализаторах для каждого из них является очень желательным. Наличие всего остального кода синтаксического анализатора в одном классе «шаблон» облегчит сохранение, чтение и отладку кода.
Очевидно, что проблема у меня есть isKindOfClass
не принимает int
, float
или BOOL
в качестве входов. Есть ли что-то подобное, что я могу использовать вместо этого?
Общеизвестно, что делегат-парсер знает о свойствах ваших объектов. Нет ничего плохого в создании объекта NSNumber из значения XML и присвоении его объекту. Однако, если вы хотите сделать свой код немного более многоразовым, вы можете создать загрузчик для каждого из ваших классов моделей, чтобы избежать использования всего вашего кода в методе 'parser: didEndElement:'. Затем просто передайте свои атрибуты каждому загрузчику. –
@CraigOtis: Если я создаю идею «загрузчика», которую я предлагаю, мне нужно будет по существу написать собственный настраиваемый инструмент для каждого свойства в моих объектах? Так что, действительно, мне все же приходится выполнять ту же работу, что и hardcoding в методе 'didEndElement:', она просто перемещается, где эта работа выполняется, правильно? – GeneralMike
В любом случае, ваши свойства должны иметь сеттеры. Вы должны * не * полагаться на методы 'setValue: forKey:' для создания и настройки ваших объектов. –