Dies ist ein wenig komplizierter als einige Standard NSXMLParser
Code; Denn im Wesentlichen, wenn Sie nach der "shipping
" suchen, möchten Sie "6.00
", aber diese beiden Daten werden Ihnen in verschiedenen Delegate-Methoden zurückgegeben, was normal ist. Aber normalerweise würde das Element "shipping
" heißen, so dass Sie in parser:didEndElement:namespaceURI:qualifiedName:
automatisch den Elementnamen haben würden, wie er an die Methode übergeben wurde.
Die Lösung wäre einfach erscheinen, haben eine _currentAttributes
Ivar und in parser:didStartElement:namespaceURI:qualifiedName:attributes:
wie _currentAttributes = attributeDict;
etwas zu tun, und diese dann in der didEndElement:
Methode zu behandeln. Allerdings würde dieser Stil leicht brechen, selbst auf diesem mäßig einfachen XML
.
Meine Art, dies zu handhaben, wäre, das Attributverzeichnis zu speichern, das an die didStartElement:
übergeben wurde, und es in einem Wörterbuch als Objekt für den Schlüssel des Elementnamens festzulegen. Kombinieren Sie diesen Stil mit der Standard-Verwendung eines NSMutableString
als characterBuffer von Arten können Sie alle Ihre Logik in die didEndElement:
-Methode setzen.
Seitennotiz: Ich bin auch ziemlich gerne meine NSXMLParserDelegate
Klassen NSXMLParser
Unterklassen, wie dieser ist. Die Delegiertenmethoden wären jedoch identisch, wenn dies nicht der Fall wäre.
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
Und so testen ich die gespeicherte XML
Sie oben in eine dem Namen "ItemXML.xml" Datei geschrieben. Und es getestet mit diesem Code:
NSURL *url = [[NSBundle mainBundle] URLForResource:@"ItemXML" withExtension:@"xml"];
ItemParser *parser = [[ItemParser alloc] initWithContentsOfURL:url];
[parser parse];
NSLog(@"%@",parser.itemData);
Das Ergebnis, das ich bekam, war:
{
currency = USD;
items = "24.00";
shipping = "6.00";
status = OK;
symbol = "$";
tax = "1.57";
}
Thank you so much. – Cam