关于解析category
,那是didStartElement
从attributes
字典中检索的 when elementName
is @"Product"
。
就“最佳方法”而言,您只需要决定您的数据结构。我可能会建议构建一个 NSMutableArray,它是一个类别字典条目数组,每个类别一个,字典中的一个对象将是该类别中的一个产品数组。
一旦你有了这个结构,回答你的第三个问题可能是显而易见的。
好的,首先,您的 XML 确实需要一个外部标记,例如:
<Products>
<Product category="ABC">
<Item_number>123</Item_number>
<Description>Coffee table</Description>
</Product>
<Product category="ABC">
<Item_number>456</Item_number>
<Description>Lamp shade</Description>
</Product>
<Product category="XYZ">
<Item_number>789</Item_number>
<Description>Orange chair</Description>
</Product>
</Products>
其次,假设您想要一个类别数组,并且对于每个类别,您想要一个产品数组,实现可能如下所示。首先,您需要一些属性,一个用于最终结果,另外两个用于解析期间使用的临时变量:
// this is our final result, an array of dictionaries for each categor
@property (nonatomic, strong) NSMutableArray *categories;
// these are just temporary variables used during the parsing
@property (nonatomic, strong) NSMutableString *parserElementValue;
@property (nonatomic, strong) NSMutableDictionary *parserProduct;
然后这些NSXMLParserDelegate
方法可能如下所示:
#pragma mark - NSXMLParser delegate methods
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
self.categories = [NSMutableArray array];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSArray *subElementNames = @[@"Item_number", @"Description"];
if ([elementName isEqualToString:@"Product"])
{
// get the name of the category attribute
NSString *categoryName = [attributeDict objectForKey:@"category"];
NSAssert(categoryName, @"no category found");
// search our array of dictionaries of cateogries to see if we have one with a name equal to categoryName
__block NSMutableDictionary *parserCurrentCategory = nil;
[self.categories enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([categoryName isEqualToString:[obj objectForKey:@"name"]])
{
parserCurrentCategory = obj;
*stop = YES;
}
}];
// if we didn't find one, let's create one and add it to our array of cateogires
if (!parserCurrentCategory)
{
parserCurrentCategory = [NSMutableDictionary dictionaryWithObjectsAndKeys:
categoryName, @"name",
[NSMutableArray array], @"items",
nil];
[self.categories addObject:parserCurrentCategory];
}
// Now let's add an entry to the items array for the product being added
self.parserProduct = [NSMutableDictionary dictionary];
[[parserCurrentCategory objectForKey:@"items"] addObject:self.parserProduct];
}
else if ([subElementNames containsObject:elementName])
{
self.parserElementValue = [NSMutableString string];
[self.parserProduct setObject:self.parserElementValue forKey:elementName];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.parserElementValue)
[self.parserElementValue appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"Product"])
{
self.parserProduct = nil;
}
else if (self.parserElementValue)
{
self.parserElementValue = nil;
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
// all done, do whatever you want, just as reloadData for your table
NSLog(@"%s categories = %@", __FUNCTION__, self.categories);
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(@"%s error=%@", __FUNCTION__, parseError);
}