2012-04-05 2 views
0

Это первый раз, используя NSXMLParser и интересно, если вы дать мне направление разбора возвращенный XML из запроса HTTP, который выглядит как:IOS: Разбор XML с HTTP, используя NSXMLParser для

<?xml version="1.0" ?> 
<theresponse> 
<status>OK</status> 
<pricing currency="USD" symbol="$"> 
    <price class="items">24.00</price> 
    <price class="shipping">6.00</price> 
    <price class="tax">1.57</price> 
</pricing> 
</theresponse> 

Я знаю, что основной методов делегирования парсинга, я просто хочу знать, как будет выглядеть код в didEndElement/foundCharacters/didStartElement для возврата выше пунктов (валюта/предметы/отправка/налог)? любая помощь очень ценится.

ответ

1

Это немного сложнее, чем какой-либо стандартный код NSXMLParser; Потому что, когда вы ищете «shipping», вы хотите «6.00», но эти две части данных возвращаются вам в разных методах делегатов, что является нормальным. Но обычно элемент будет называться «shipping», поэтому в parser:didEndElement:namespaceURI:qualifiedName: вам будет автоматически присвоено имя элемента, как оно было передано в метод.

Решение может показаться простым, есть _currentAttributes Ивара и в parser:didStartElement:namespaceURI:qualifiedName:attributes: сделать что-то вроде _currentAttributes = attributeDict;, а затем справиться с этим в методе didEndElement:. Однако этот стиль легко сломался, даже на этом умеренно простом XML.

Моим способом обработки этого было бы сохранить словарь атрибутов, переданный в didStartElement:, и установить его в словаре как объект для ключа имени элемента. Объединив этот стиль со стандартным использованием NSMutableString в качестве характерного буфера, вы можете поместить всю свою логику в метод didEndElement:.

Сторона примечания: Я также очень люблю, чтобы мои классы NSXMLParserDelegate были NSXMLParser подклассами, как этот. Однако методы делегата были бы идентичны, если бы это было не так.

ItemParser.h

#import <Foundation/Foundation.h> 
@interface ItemParser : NSXMLParser <NSXMLParserDelegate> 
@property (readonly) NSDictionary *itemData; 
@end 

ItemParser.m

#import "ItemParser.h" 
@implementation ItemParser { 
    NSMutableDictionary *_itemData; 
    NSMutableDictionary *_attributesByElement; 
    NSMutableString *_elementString; 
} 
-(NSDictionary *)itemData{ 
    return [_itemData copy]; 
} 
-(void)parserDidStartDocument:(NSXMLParser *)parser{ 
    _itemData = [[NSMutableDictionary alloc] init]; 
    _attributesByElement = [[NSMutableDictionary alloc] init]; 
    _elementString = [[NSMutableString alloc] init]; 
} 
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ 
    // Save the attributes for later. 
    if (attributeDict) [_attributesByElement setObject:attributeDict forKey:elementName]; 
    // Make sure the elementString is blank and ready to find characters 
    [_elementString setString:@""]; 
} 
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ 
    // Save foundCharacters for later 
    [_elementString appendString:string]; 
} 
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ 
    if ([elementName isEqualToString:@"status"]){ 
     // Element status only contains a string i.e. "OK" 
     // Simply set a copy of the element value string in the itemData dictionary 
     [_itemData setObject:[_elementString copy] forKey:elementName]; 
    } else if ([elementName isEqualToString:@"pricing"]) { 
     // Pricing has an interesting attributes dictionary 
     // So copy the entries to the item data 
     NSDictionary *attributes = [_attributesByElement objectForKey:@"pricing"]; 
     [_itemData addEntriesFromDictionary:attributes]; 
    } else if ([elementName isEqualToString:@"price"]) { 
     // The element price occurs multiple times. 
     // The meaningful designation occurs in the "class" attribute. 
     NSString *class = [[_attributesByElement objectForKey:elementName] objectForKey:@"class"]; 
     if (class) [_itemData setObject:[_elementString copy] forKey:class]; 
    } 
    [_attributesByElement removeObjectForKey:elementName]; 
    [_elementString setString:@""]; 
} 
-(void)parserDidEndDocument:(NSXMLParser *)parser{ 
    _attributesByElement = nil; 
    _elementString = nil; 
} 
-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{ 
    NSLog(@"%@ with error %@",NSStringFromSelector(_cmd),parseError.localizedDescription); 
} 
-(BOOL)parse{ 
    self.delegate = self; 
    return [super parse]; 
} 
@end 

И так, чтобы проверить, я хранилась XML вы вывесили выше в файл с именем "ItemXML.xml". И протестировали его, используя этот код:

NSURL *url = [[NSBundle mainBundle] URLForResource:@"ItemXML" withExtension:@"xml"]; 
ItemParser *parser = [[ItemParser alloc] initWithContentsOfURL:url]; 
[parser parse]; 
NSLog(@"%@",parser.itemData); 

В результате я получил:

{ 
    currency = USD; 
    items = "24.00"; 
    shipping = "6.00"; 
    status = OK; 
    symbol = "$"; 
    tax = "1.57"; 
} 
+0

Благодарю вас так много. – Cam

0

Отъезд tutorial. В нем объясняется, как использовать NSXMLParser для анализа данных из XML в собственный формат данных.

Смежные вопросы