我试图找出使用xmlparser委托解析xml的大型数据集的最佳方法..(基本上我将数据放入了什么?)
xml数据将如下所示。
<Rows>
<Row ID="76" MANF="JARD" ISMANUF="F" ISSER="F"/>
<Row ID="38" MANF ="SANBIN" ISMANUF ="F" ISSER ="T"/>
<Rows>
我正在寻找高水平的回复,所以我可以离开并做更多的研究,因为他们显然有几种不同的方式来解决这个问题。我想知道最好/最有效的存储数据来自NSXMLParser,也想要我能够缓存的东西......
到目前为止,我一直在关注NSMutabledictionarys但是听说过这可能不太可能,所以我现在开始考虑创建自己的对象..但是从我的解析委托返回的数据只与字符串兼容..所以如果我有一个bool值我不能把它放进我的对象..任何帮助都会非常感激,因为我有点不知所措。
答案 0 :(得分:2)
我已经实现了一个足够有效的XML-to-NSDictionary
解析器。如果您愿意,可以将其作为NSMutableDictionary
返回。我目前没有github或其他任何东西,所以我会在这里发布代码内联。它使用了TBXML
XML解析库(没有XPath支持,只读解析,但是相当高效和高级)。
编辑:我刚刚意识到,我的解析器是用来解析元素中的元素名称和文本,而不是元素属性,这就是你的XML数据集的放置方式出。不幸的是,下面的代码不会解析属性。您已经有了一个起点,您可以更改使用->firstChild
和->nextSibling
来读取属性的代码。
<强> XML.h 强>
@interface XML : NSObject
/**
* Constructs an NSDictionary from the provided XML tree.
*
* Uses the default prefix of 'config'.
*/
+ (NSDictionary *)dictionaryForXMLTree:(TBXMLElement *)tree;
/**
* Constructs an NSDictionary from the provided XML tree.
*
* The format of the dictionary keys is:
* section/[subsection/.../]optionName
*/
+ (NSDictionary *)dictionaryForXMLTree:(TBXMLElement *)tree
withPrefix:(NSString *)keyPrefix;
/**
* Iteratively parses configuration areas from the provided XML document.
*
* If an 'list' area is encountered, its immediate children are added to
* the dictionary as a numbered list (i.e list/1/..., list/2/...).
*/
+ (NSDictionary *)dictionaryFromXML:(TBXML *)xmlDoc;
@end
<强> XML.m 强>
NSString *stripHTML(const char* xmlString);
NSString* stripHTML(const char* xmlString)
{
return [[[NSString stringWithUTF8String:xmlString]
stringByReplacingOccurrencesOfString:@"&"
withString:@"&"]
stringByReplacingOccurrencesOfString:@" "
withString:@""];
}
@implementation XML
@synthesize configDict;
#pragma mark - XML parsing
+ (NSDictionary *)itemisedDictionaryForXMLTree:(TBXMLElement *)tree
withPrefix:(NSString *)keyPrefix
{
NSMutableDictionary *returnValues =
[[NSMutableDictionary alloc] init];
NSUInteger itemNumber = 1;
for (TBXMLElement *option = tree->firstChild;
option != nil;
option = option->nextSibling)
{
if(option->text == NULL)
option->text = "";
NSString *childPrefix = [NSString stringWithFormat:@"%@/%u",
keyPrefix, itemNumber++];
[returnValues setObject:stripHTML(option->text)
forKey:childPrefix];
[returnValues addEntriesFromDictionary:
[self dictionaryForXMLTree:option withPrefix:childPrefix]];
}
return [returnValues autorelease];
}
+ (NSDictionary *)dictionaryForXMLTree:(TBXMLElement *)tree
withPrefix:(NSString *)keyPrefix
{
NSMutableDictionary *returnValues =
[[NSMutableDictionary alloc] init];
for (TBXMLElement *option = tree->firstChild;
option != nil;
option = option->nextSibling)
{
if(option->text == NULL)
option->text = "";
NSString *childPrefix = [NSString stringWithFormat:@"%@/%s",
keyPrefix,
option->name];
[returnValues setObject:stripHTML(option->text)
forKey:childPrefix];
[returnValues addEntriesFromDictionary:
[self dictionaryForXMLTree:option withPrefix:childPrefix]];
}
return [returnValues autorelease];
}
+ (NSDictionary *)dictionaryForXMLTree:(TBXMLElement *)tree
{
return [self dictionaryForXMLTree:tree withPrefix:@"config"];
}
+ (NSDictionary *)dictionaryFromXML:(TBXML *)xmlDoc
{
NSMutableDictionary *config = [[NSMutableDictionary alloc] init];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
TBXMLElement *rootElement = [xmlDoc rootXMLElement];
if(rootElement != nil)
{
for(TBXMLElement *configArea = rootElement->firstChild;
configArea != nil;
configArea = configArea->nextSibling)
{
NSString *areaName = [NSString stringWithFormat:@"%s",
configArea->name];
if([areaName
isEqualToString:@"list"]) // multiple children with the same name
{
[config addEntriesFromDictionary:
[self itemisedDictionaryForXMLTree:configArea
withPrefix:areaName]];
} else {
[config addEntriesFromDictionary:
[self dictionaryForXMLTree:configArea
withPrefix:areaName]];
}
}
}
[pool release];
return [config autorelease];
}
+ (NSDictionary *)fetchConfig:(NSURL *)atURL
{
TBXML *xmlDoc = [TBXML tbxmlWithURL:atURL];
return [XML dictionaryFromXML:xmlDoc];
}
+ (NSDictionary *)parseConfigFromXMLString:(NSString *)xmlString
{
TBXML *xmlDoc = [TBXML tbxmlWithXMLString:xmlString];
return [XML dictionaryFromXML:xmlDoc];
}